[LMKD] [Android] 进程OomAdj调整分析:OomAdjuster分析(3)

一.简要说明

二.源码分析

  	/**
     * Update OomAdj for specific process and its reachable processes (with direction/indirect
     * bindings from this process); Note its clients' proc state won't be re-evaluated if this proc
     * is hosting any service/content provider.
     *
     * @param app The process to update, or null to update all processes
     * @param oomAdjReason
     */
    @GuardedBy("mService")
    boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
        synchronized (mProcLock) {
            return updateOomAdjLSP(app, oomAdjReason);
        }
    }

传递2个参数,第一个是进程实体,第二个是调整的意思,整个方法有一把锁mService,而方法内也持有一把锁ActivityManagerGlobalLock mProcLock,继续看看updateOomAdjLSP

  	@GuardedBy({"mService", "mProcLock"})//两把锁
    private boolean updateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
        // 应用启动流程,在AMS中会调用到这里来,ProcessRecord刚创建出来,ActivityThread进程还没fork出来
        // 这里的app是ProcessRecord,不为空,所以不走这里
        if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
            updateOomAdjLSP(oomAdjReason);
            return true;
        }

        if (checkAndEnqueueOomAdjTargetLocked(app)) {
            // Simply return true as there is an oomAdjUpdate ongoing
            return true;
        }

        try {
            // 走这
            **mOomAdjUpdateOngoing** = true;
            **return performUpdateOomAdjLSP(app, oomAdjReason);**
        } finally {
            // Kick off the handling of any pending targets enqueued during the above update
            mOomAdjUpdateOngoing = false;
            updateOomAdjPendingTargetsLocked(oomAdjReason);
        }
    }

继续看看performUpdateOomAdjLSP(两个参数)方法

@GuardedBy({"mService", "mProcLock"})
    private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) {// odj调整leilei
        // 获取顶部activity---通常正在运行
        final ProcessRecord topApp = mService.getTopApp();

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
        // oomAdj调整开始的标志,记录了开始的时间和mOomAdjStarted为true
        mService.mOomAdjProfiler.oomAdjStarted();
        // 调整的序列号++,该序列号会用于判断调整是否完成
        mAdjSeq++;

        // Firstly, try to see if the importance of itself gets changed
        // 获取要调整进程的进程状态,ProcessStateRecord保存了该进程状态
        final ProcessStateRecord state = app.mState;
        // 是否属于cache进程,属于cache进程代表进程随时被杀死或者已经杀死
        final boolean wasCached = state.isCached();
        // 先记录之前该app进程的优先级,getCurRawAdj代表获取的原始adj--原始adj代表没有被约束过的进程adj值--进程adj值是会被约束的
        final int oldAdj = state.getCurRawAdj();
        // 如果oldAdj >=900,说明属于Empty或cache进程
        final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
                ? oldAdj : ProcessList.UNKNOWN_ADJ;
        // 是否属于后台进程---调整的是进程,而非单个对象
        final boolean wasBackground = ActivityManager.isProcStateBackground(
                state.getSetProcState());
        // 记录进程能力,例如可访问网络,可访问地理位置等能力
        final int oldCap = state.getSetCapability();
        // 是否重复计算进程,也就是进程计算oom adj不止一次,需要计算好几次
        state.setContainsCycle(false);
        state.setProcStateChanged(false);
        state.resetCachedInfo();
        // Check if this process is in the pending list too, remove from pending list if so.
        // 如果进程属于挂起状态(待运行启动状态),则从该集合中移除
        mPendingProcessSet.remove(app);
        // 进入另一个performUpdateOomAdjLSP,主要目的是调用computeOomAdjLSP,计算进程adj优先级
        // 计算过后通过apply应用计算出来的adj值,也就是会调用 ProcessList.setOomAdj(),然后修改state.setCurAdj(),应用进程的adj
        boolean success = **performUpdateOomAdjLSP**(app, cachedAdj, topApp,
                SystemClock.uptimeMillis());
			 ...
}

继续看看performUpdateOomAdjLSP(四个参数)方法

  	@GuardedBy({"mService", "mProcLock"})
    private boolean performUpdateOomAdjLSP(ProcessRecord app/*待调整的进程*/, int cachedAdj/*可能是[900,999]或者无效值1001*/,
            ProcessRecord topApp/*当前的topapp*/, long now/*oom adj调整的时间*/) {
        // 当进程还没有fork出来的时候,不做调整,结束
        if (app.getThread() == null) {
            return false;
        }
				...
        // 计算oom adj的核心方法---代码超过1k行
				// computeClients代表调整当前进程的时候,也同时调整客户端进程状态,因为Service是有客户端连接的,广播是有客户端发送,内容提供者亦如此
        **computeOomAdjLSP**(app, cachedAdj, topApp, false/*doingALl*/, now, false/*cycleReEval循环计算*/, true/*computeClients*/);
        ...
        // 应用由computeOomAdjLSP计算完成后的oom adj和进程状态,这里面会进行状态约束和oomAdj约束
        return **applyOomAdjLSP**(app, false, now, SystemClock.elapsedRealtime());
    }

这里主要分析**computeOomAdjLSPapplyOomAdjLSP**两个非常重要的方法

  • computeOomAdjLSP

    这个方法非常复杂,具体如下分析

    // leilei关键代码
        @GuardedBy({"mService", "mProcLock"})
        private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj/*默认值*/,
                ProcessRecord topApp, boolean doingAll/*false*/, long now, boolean cycleReEval/*false*/,
                boolean computeClients/*true*/) {
            final ProcessStateRecord state = app.mState;
            // 每次adj调整都会自增序列id(updateOomAdjInnerLSP/performUpdateOomAdjLSP会自增),如果序列id相等,代表这个进程已经参与过本次调整
            if (mAdjSeq == state.getAdjSeq()) {
                // 当前adj已经调整完成,则直接终止
                if (state.getAdjSeq() == state.getCompletedAdjSeq()) {
                    // This adjustment has already been computed successfully.
                    return false;
                } else {
                    // The process is being computed, so there is a cycle. We cannot
                    // rely on this process's state.
                    // 设置为循环调整adj
                    state.setContainsCycle(true);
                    // 这个集合就是要循环调整adj
                    mProcessesInCycle.add(app);
    
                    return false;
                }
            }
    
            // 因为new ProcessRecord的时候就会走到这里来,但是ActivityThread还没创建,此时会走这里
            if (app.getThread() == null) {
                // 设置当前的seq,如果下次调整发现state.getAdjSeq() == mAdjSeq
                // 代表此次调整完成,如果又发现getAdjSeq == getCompletedAdjSeq,则代表adj调整完成
                // 所以每次进程调整adj,都对应了一个mAdjSeq
                state.setAdjSeq(mAdjSeq);
                // 设置进程分组,属于SCHED_GROUP_BACKGROUND组
                state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_BACKGROUND);
                // 设置进程状态为Empty(19,倒数第二优先级,倒数第一是NONEXISTENT)
                state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
                // 设置当前进程adj优先级为999,它可以在没有任何干扰的情况下被杀死
                state.setCurAdj(ProcessList.CACHED_APP_MAX_ADJ);
                state.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
                // 相当于将mAdjSeq赋值给setCompletedAdjSeq,代表调整完成
                state.setCompletedAdjSeq(state.getAdjSeq());
                // 设置进程能力为0,代表没有任何功能
                state.setCurCapability(PROCESS_CAPABILITY_NONE);
                return false;
            }
    
            // 设置默认值
            state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
            state.setAdjSource(null);
            state.setAdjTarget(null);
            state.setEmpty(false);
            state.setCached(false);
            // 重置allow start fgs state值为:PROCESS_STATE_NONEXISTENT
            state.resetAllowStartFgsState();
            // 非循环计算,设置进程可悲被冻结
            if (!cycleReEval) {
                // Don't reset this flag when doing cycles re-evaluation.
                app.mOptRecord.setShouldNotFreeze(false);
            }
    
            // 进程端的uid
            final int appUid = app.info.uid;
            final int logUid = mService.mCurOomAdjUid;
    
            // 记录当前的进程adj,通过下文会和当前的adj进行比较
            int prevAppAdj = state.getCurAdj();// 当前adj---被约束过的adj,值越小,保活率越高
            int prevProcState = state.getCurProcState();// 当前进程状态,值越小,保活率越高
            int prevCapability = state.getCurCapability();// 进程的能力,例如访问位置信息,相机等
            final ProcessServiceRecord psr = app.mServices;// 该进程的所有service集合,可能没有,与之对应的是Process{Provider/Receiver}Record
    
            // 一般系统服务的maxAdj才会小于等于FOREGROUND_APP_ADJ
            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.
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making fixed: " + app);
                }
                // 小于等于0的进程,都属于比较重要的进程
                // 所以type调整为fixed,为固定不可调整
                state.setAdjType("fixed");
                state.setAdjSeq(mAdjSeq);
                // 将进程之前设置最大adj(在processList#newProcessRecordLocked方法中
                // 会将系统进程设置setMaxAdj(ProcessList.PERSISTENT_PROC_ADJ))
                state.setCurRawAdj(state.getMaxAdj());
                // 默认是没有前景activity(默认值)
                state.setHasForegroundActivities(false);
                // 给的默认分组--分组分为SCHED_GROUP_BACKGROUND,SCHED_GROUP_TOP_APP,这两个比较常见
                state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
                // 此类进程应用拥有最大的能力,CAMERA,MICROPHONE,NETWORK,LOCATION
                state.setCurCapability(PROCESS_CAPABILITY_ALL);
                // 设置进程状态,系统进程都设置为进程持久化状态
                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) {
                    // 这类进程是带有ui的
                    state.setSystemNoUi(false);
                    // 可以在/dev/cpuset/top-app查看该分组的信息,例如top app的pid等
                    // 这里设置分组为TOP_APP
                    state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
                    // 设置adj类型
                    state.setAdjType("pers-top-activity");
                } else if (state.hasTopUi()) {// 例如下拉状态栏,锁屏界面
                    // sched group/proc state adjustment is below
                    // 例如下拉状态栏,锁屏界面,也带有UI
                    state.setSystemNoUi(false);
                    state.setAdjType("pers-top-ui");
                } else if (state.getCachedHasVisibleActivities()) {// 如果有可见的activity,不论是否前台
                    // 设置为有UI
                    state.setSystemNoUi(false);
                }
                //只有带有界面的常驻进程才会进入这里面(如systemui会灭屏幕进入;phone进程灭屏由于isSystemNoUi是true所以不进入)
                if (!state.isSystemNoUi()) {// 带有界面的进程
                    // 如果是亮屏状态
                    if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE
                            || state.isRunningRemoteAnimation()) {
                        // screen on or animating, promote UI
                        // 如果是亮屏状态或者播放动画状态,提升进程状态为 常驻进程UI
                        state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
                        // 分组提升到TOP APP
                        state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
                    } else {
                        // screen off, restrict UI scheduling
                        // 如果是灭屏,进程状态切换到PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                        state.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
                        // 分组切换到RESTRICTED,存在限制的进程分组
                        state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_RESTRICTED);
                    }
                }
                // 设置原始的进程状态--还未被限制
                state.setCurRawProcState(state.getCurProcState());
                // 可以看到系统进程,默认都没有调整adj。而是直接指定当时的最大值adj
                state.setCurAdj(state.getMaxAdj());
                // 设置调整完成后的序列号
                state.setCompletedAdjSeq(state.getAdjSeq());
                // 代表是否允许启动前台服务
                state.bumpAllowStartFgsState(state.getCurProcState());
                // if curAdj is less than prevAppAdj, then this process was promoted
                // 只有调整后的优先级更小,或者进程状态比之前的更新,才算是有效调整
                return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
            }
    
            // 非系统进程会继续走到这里,默认设置没有ui
            state.setSystemNoUi(false);
    
            // 获取top进程的状态,TOP_SLEEPING或者TOP
            final int PROCESS_STATE_CUR_TOP = mService.mAtmInternal.getTopProcessState();
    
            // Determine the importance of the process, starting with most
            // important to least, and assign an appropriate OOM adjustment.
            int adj;//进程adj
            int schedGroup;//分组
            int procState;//进程状态
            int cachedAdjSeq;
            int capability = 0;//进程能力
    
            // 默认没有前景activity,默认activity不可见
            boolean foregroundActivities = false;
            boolean hasVisibleActivities = false;
            // 如果当前有top app,并且当前是唤醒状态(如亮屏),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.
                // 也就是当前app处于前台,那么adj默认给到0:FOREGROUND_APP_ADJ
                // 可以在/proc/pid/oom_score_adj,查看当前进程的adj值
                adj = ProcessList.FOREGROUND_APP_ADJ;
                // 默认分组TOP APP
                schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                // type也为top activity
                state.setAdjType("top-activity");
                // 前台app当然可见
                foregroundActivities = true;
                hasVisibleActivities = true;
                // 进程状态,top
                procState = PROCESS_STATE_CUR_TOP;
                // 将是否允许启动前台service的状态设置成PROCESS_STATE_TOP
                // 进程状态不低于PROCESS_STATE_BOUND_FOREGROUND_SERVICE即可启动前台服务
                // mAllowStartFgsState(也就是PROCESS_STATE_TOP赋予的) <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                // 2 <= 5条件成立,所以是可以启动前台service的
                state.bumpAllowStartFgsState(PROCESS_STATE_TOP);
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app);
                }
            } else if (state.isRunningRemoteAnimation()) {// 如果正在播放动画
                // 如果处于远程动画播放状态,则会提高进程优先级为:可见adj
                adj = ProcessList.VISIBLE_APP_ADJ;
                // 设置top app分组
                schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                state.setAdjType("running-remote-anim");
                // 进程状态也为top
                procState = PROCESS_STATE_CUR_TOP;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making running remote anim: " + app);
                }
            } else if (app.getActiveInstrumentation() != null) {//进程中存在instrumentation在活跃
                // Don't want to kill running instrumentation.
                // 提高instrumentation优先级:0
                adj = ProcessList.FOREGROUND_APP_ADJ;
                // 分组到默认,而不是top app
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                state.setAdjType("instrumentation");
                // 进程状态设置为前台服务:4
                procState = PROCESS_STATE_FOREGROUND_SERVICE;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
                }
            } 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.
                // 当前正在接收广播的应用程序也被视为处于OOM杀手目的的前台。
                // 它被放置在一个sched组中,该组基于广播的性质,如它在哪个队列中活动所反映的
                // 因为正在接收广播,所以也算是前台app,优先级提高到0
                adj = ProcessList.FOREGROUND_APP_ADJ;
                // 如果是前台广播,则放到默认分组,如果是后台广播则放到后台分组
                schedGroup = (mTmpBroadcastQueue.contains(mService.mFgBroadcastQueue))
                        ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
                state.setAdjType("broadcast");
                // 进程状态:正在接收广播
                procState = ActivityManager.PROCESS_STATE_RECEIVER;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making broadcast: " + app);
                }
            } else if (psr.numberOfExecutingServices() > 0) {// 正在运行的服务,保存到ArraySet<ServiceRecord> mExecutingServices = new ArraySet<>();
                // An app that is currently executing a service callback also
                // counts as being in the foreground.
                // 当前正在执行服务回调的应用程序也被视为处于前台
                // 由于当前app中存在服务正在运行,所以该app也调整为前台
                // 注意这不是调整的服务进程adj,而是调整的app进程
                adj = ProcessList.FOREGROUND_APP_ADJ;
                // 如果正在执行前台服务,则调整到默认分组,如果是后台服务则调整到后台分组
                schedGroup = psr.shouldExecServicesFg()
                        ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
                state.setAdjType("exec-service");
                // 进程状态:服务
                procState = PROCESS_STATE_SERVICE;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
                }
            } else if (app == topApp) {// 如果是top app,但是处于灭屏状态,因为亮屏且top app不会在此分支上执行
                // top app但是处于灭屏状态,进程adj也是属于前台类别
                // 经测试,确实是这样
                adj = ProcessList.FOREGROUND_APP_ADJ;
                // 分组分配到了后台
                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                state.setAdjType("top-sleeping");
                // 拥有前台activity
                foregroundActivities = true;
                // 进程状态:PROCESS_STATE_CUR_TOP_SLEEP
                procState = PROCESS_STATE_CUR_TOP;
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top (sleeping): " + app);
                }
            } else {// 其他情况,默认后台分组
                // As far as we know the process is empty.  We may change our mind later.
                schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                // At this point we don't actually know the adjustment.  Use the cached adj
                // value that the caller wants us to.
                // adj默认值,或者上次调整的值
                adj = cachedAdj;
                // 进程状态属于empty
                procState = PROCESS_STATE_CACHED_EMPTY;
                // 非循环计算,说明adj已经计算完成了,此时就设置为empty
                // 超过10个empty,empty就会被依次kill
                if (!state.containsCycle()) {
                    state.setCached(true);
                    state.setEmpty(true);
                    state.setAdjType("cch-empty");
                }
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making empty: " + app);
                }
            }
    
            // Examine all activities if not already foreground.
            // foregroundActivities目前只有top app才是true,除了了top它的值都是false
            // 只要进程有activity(getCachedHasActivities其实是hasActivities),则getCachedHasActivities返回true
            if (!foregroundActivities && state.getCachedHasActivities()) {
                // 通过activity不同的状态计算其adj
                //  if ((flags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) {// 如果activity可见,则处理onVisibleActivity
                //            callback.onVisibleActivity();
                //        } else if ((flags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) {//如果activity处于pausing~paused,则执行onPausedActivity
                //            callback.onPausedActivity();
                //        } else if ((flags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) {//如果activity stop,则执行onStoppingActivity
                //            callback.onStoppingActivity(
                //                    (flags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0);
                //        } else {//其他情况
                //            callback.onOtherActivity();
                //        }
                //   }
                // 以上的callback就是mTmpComputeOomAdjWindowCallback
                // 会根据activity不同的状态,调整不同的adj,例如onVisibleActivity被调用了,则会执行以下逻辑:
                // 1.activity处于可见状态,但是其adj<VISIBLE_APP_ADJ,那么就会重新修改adj = VISIBLE_APP_ADJ
                // 2.然后进程分组会分配到默认分组
                // 3.进程状态会被设置为processStateCurTop,且setEmpty和setCache会改为false
                // 4.设置为具有前台activity且设置为可见状态foregroundActivities = true mHasVisibleActivities = true;
                state.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
                        adj, foregroundActivities, hasVisibleActivities, procState, schedGroup,
                        appUid, logUid, PROCESS_STATE_CUR_TOP);
    
                // getCachedAdj的值会在computeOomAdjFromActivitiesIfNecessary重新修改
                // 将computeOomAdjFromActivitiesIfNecessary重新计算的值赋值给adj
                adj = state.getCachedAdj();
                // foregroundActivities和hasVisibleActivities也会被重新修改,在computeOomAdjFromActivitiesIfNecessary重新计算
                foregroundActivities = state.getCachedForegroundActivities();
                hasVisibleActivities = state.getCachedHasVisibleActivities();
                // 同上,computeOomAdjFromActivitiesIfNecessary会重新计算
                procState = state.getCachedProcState();
                schedGroup = state.getCachedSchedGroup();
            }
    
            // 有activity在最近任务mRecentTasks,代表最近启动的activity,进程状态设置成小于等于PROCESS_STATE_CACHED_RECENT
            // 这里的条件就是:近期任务中存在该进程,但是进程状态又比PROCESS_STATE_CACHED_RECENT高,则设置回PROCESS_STATE_CACHED_RECENT
            if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) {
                procState = PROCESS_STATE_CACHED_RECENT;
                state.setAdjType("cch-rec");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
                }
            }
    
            // 如果adj大于可感知的优先级,或者进程状态大于前台服务
            // 这里主要就是处理 adj和进程状态都处于低迷状态,但是实际上进程处于前台,则将进程状态和adj重新拉高,保证其保活率
            if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                    || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
                // 属于前台服务,但是adj不属于可感知范围内,进程状态也不在前台服务范围内
                // 那么就调整回PERCEPTIBLE_APP_ADJ:可感知优先级
                // 进程状态也改回前台服务PROCESS_STATE_FOREGROUND_SERVICE
                if (psr.hasForegroundServices()) {
                    // The user is aware of this app, so make it visible.
                    adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                    procState = PROCESS_STATE_FOREGROUND_SERVICE;
                    state.bumpAllowStartFgsState(PROCESS_STATE_FOREGROUND_SERVICE);
                    state.setAdjType("fg-service");
                    state.setCached(false);
                    // 默认分组
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + state.getAdjType() + ": "
                                + app + " ");
                    }
                } else if (state.hasOverlayUi()) {// 如果是overlay ui(需要设置TYPE_APPLICATION_OVERLAY,有覆盖之上的界面,类似悬浮窗)
                    // The process is display an overlay UI.
                    // adj也设置为可感知adj
                    adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                    // 进程状态设置为重要的前台进程
                    procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
                    state.setCached(false);
                    state.setAdjType("has-overlay-ui");
                    // 默认分组
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to overlay ui: " + app);
                    }
                }
            }
    
            // If the app was recently in the foreground and moved to a foreground service status,
            // allow it to get a higher rank in memory for some time, compared to other foreground
            // services so that it can finish performing any persistence/processing of in-memory state.
            // 1.如果应用程序最近处于前台并移动到前台服务状态,则与其他前台服务相比,
            // 允许它在一段时间内在内存中获得更高的级别,以便它可以完成对内存状态的任何持久化/处理。
            // 2.也就是 : 调整最近活跃的前台服务进程,在一段时间内(15s),继续像对待前台应用程序一样对待它。
            // 3.处理,进程被移动到后台,不活跃时的状态:15s内在top级别(最前台),会被调整跟前台进程一样的待遇。
            // 4.或者进程处于PROCESS_STATE_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)) {
                // 设置为PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,即虽然进程在调整到后台了或者不活跃了,在一段时间内,继续像对待前台应用程序一样对待它
                adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
                state.setAdjType("fg-service-act");
                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                    reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
                }
            }
    
            // 处理:adj大于了可感知优先级,进程大于了后台状态,但是进程又处于很重要的状态
            if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                    || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
                // 进程处于重要状态(调用AMS的setProcessImportant设置-->强制设置为进程重要状态)
                // 这种情况用于:想要进程让用户感知,但又不想设置其优先级,就可以通过setProcessImportant来设置
                // 一般toast是这么做的
                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
                    adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                    // 设置进程状态为后台--进程处于临时后台,因此我们将尝试继续运行
                    procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
                    state.setCached(false);
                    state.setAdjType("force-imp");
                    state.setAdjSource(state.getForcingToImportant());
                    // 默认分组
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to force imp: " + app);
                    }
                }
            }
    
            // 当app无法保存状态,如AndroidManifest.xml设置了"android:cantSaveState="true"",
            // 同时系统配置了<feature name="android.software.cant_save_state" />这个feature
            // 由于其无法保存状态,故尽量不要杀死, 一般只有一个,adj类型是"heavy"
            if (state.getCachedIsHeavyWeight()) {
                if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                    // We don't want to kill the current heavy-weight process.
                    // 我们不想扼杀目前具有繁重工作的进程
                    adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
                    schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                    state.setCached(false);
                    state.setAdjType("heavy");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to heavy: " + app);
                    }
                }
                if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                    procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
                    state.setAdjType("heavy");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to heavy: " + app);
                    }
                }
            }
    
            // 如果是launcher应用,该应用的优先级都不算太高
            // 但根据实际验证,桌面会一直保持在100(可见的优先级),如果回到桌面 ,则会调整到0:前台应用
            // 因为一般走不到这里来,会在以上的top app中进行处理了
            if (state.getCachedIsHomeProcess()) {
                // 桌面应用的adj不能大于600(HOME_APP_ADJ),launcher应用的adj大于了HOME_APP_ADJ,则默认调整回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 = ProcessList.HOME_APP_ADJ;
                    // launcher是个特殊应用,一直都会处于后台分组,但又需要保证不被kill
                    schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                    state.setCached(false);
                    state.setAdjType("home");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to home: " + app);
                    }
                }
                // 进程状态也设置为PROCESS_STATE_HOME
                if (procState > ActivityManager.PROCESS_STATE_HOME) {
                    procState = ActivityManager.PROCESS_STATE_HOME;
                    state.setAdjType("home");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to home: " + app);
                    }
                }
            }
    
            // 1. getCachedIsPreviousProcess: 在上一个前台进程activity stop的时候,则会将进程ActivityRecord的app(WindowProcessController)加入到mPreviousProcess,做为上一个进程
            // 2. getCachedHasActivities:在realStartActivityLocked()的时候将activity add进来,在detachFromProcess或者destroyImmediately()的时候移除activity,
            // 也就是说是否有启动过但是未destory的activity(上个进程仍存在的情况),只针对activity
            // PREVIOUS_APP_ADJ解释:这是用户所在的上一个应用程序的过程。这个过程高于其他过程,因为切换回上一个程序是非常常见的
            if (state.getCachedIsPreviousProcess()/*上一个进程*/ && state.getCachedHasActivities()/*此次进程*/) {
                // 如果存在上一个进程activity,则adj默认给到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 = ProcessList.PREVIOUS_APP_ADJ;
                    // 设置为后台分组
                    schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                    state.setCached(false);
                    state.setAdjType("previous");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
                    }
                }
                // 进程状态设置为最新启动的activity
                if (procState > PROCESS_STATE_LAST_ACTIVITY) {
                    procState = PROCESS_STATE_LAST_ACTIVITY;
                    state.setAdjType("previous");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
                    }
                }
            }
    
            if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
                    + " reason=" + state.getAdjType());
    
            // By default, we use the computed adjustment.  It may be changed if
            // there are applications dependent on our services or providers, but
            // this gives us a baseline and makes sure we don't get into an
            // infinite recursion. If we're re-evaluating due to cycles, use the previously computed
            // values.
            // cycleReEval只有在设置了setContainsCycle true(如正在计算computeOomAdjLSP的时候还没计算完又跑进来,
            // 如上面的mAdjSeq == state.getAdjSeq()或者(services/provider的客户端有这种情况的时候---也就是会递归调用computeOomAdjLSP)),
            // 在updateOomAdjInnerLSP会让cycleReEval=true
            // 如果是循环计算的话
            if (cycleReEval) {
                // 取之前的进程状态getCurRawProcState和上面计算出来的进程状态procState的最小值,值越小,保活率越高
                procState = Math.min(procState, state.getCurRawProcState());
                // 取之前的进程adj(getCurRawAdj--原始adj)和上面计算出来的adj的最小值,值越小,保活率越高
                adj = Math.min(adj, state.getCurRawAdj());
                // 取最大分组
                schedGroup = Math.max(schedGroup, state.getCurrentSchedulingGroup());
            }
            // 设置原始adj,也就是未被约束的adj
            state.setCurRawAdj(adj);
            // 设置原始进程状态,也就是未被约束的procState
            state.setCurRawProcState(procState);
    
            state.setHasStartedServices(false);
            // 设置此次的序列号
            state.setAdjSeq(mAdjSeq);
    
            // 处理backup应用
            final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
            if (backupTarget != null && app == backupTarget.app) {
                // If possible we want to avoid killing apps while they're being backed up
                if (adj > ProcessList.BACKUP_APP_ADJ) {
                    if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
                    adj = ProcessList.BACKUP_APP_ADJ;
                    if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
                        procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
                    }
                    state.setAdjType("backup");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to backup: " + app);
                    }
                    state.setCached(false);
                }
                if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
                    procState = ActivityManager.PROCESS_STATE_BACKUP;
                    state.setAdjType("backup");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to backup: " + app);
                    }
                }
            }
    
            // 这里开始就是处理四大组件的service了
            // service服务自身和服务依赖关系调整,也就是activity客户端和services服务端的adj调整,他们之间有依赖关系
            // 用于计算前台服务都拥有哪些能力,能力默认0
            int capabilityFromFGS = 0; // capability from foreground service.
            // 用来用来判断分组是否需要将分组设置成top
            boolean scheduleLikeTopApp = false;
            // 获取正在运行的服务(只要startService了就会放入ProcessServiceRecord的mServices中,stopService或者kill会从mServices移除)
            // 且必须adj大于前台app,或者属于后台分组,或者比PROCESS_STATE_TOP状态还大
            // 处理正在运行的服务的adj状态和进程状态---也就是服务正在运行,但是adj却太高了,做进一步处理
            for (int is = psr.numberOfRunningServices() - 1;
                    is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                            || procState > PROCESS_STATE_TOP);
                    is--) {
                // 获取当前进程运行的其中一个服务
                ServiceRecord s = psr.getRunningServiceAt(is);
                // startRequested是在startServiceInnerLocked中设置(服务启动过程),
                // 在realStartServiceLocked(会将service放入mServices)之前
                if (s.startRequested) {
                    // 设置服务正处于运行,因为startRequested为true
                    state.setHasStartedServices(true);
                    // PROCESS_STATE_SERVICE(10) > PROCESS_STATE_TOP(2)
                    // 如果进程状态比PROCESS_STATE_SERVICE还大,则默认调整回PROCESS_STATE_SERVICE
                    if (procState > PROCESS_STATE_SERVICE) {
                        procState = PROCESS_STATE_SERVICE;
                        state.setAdjType("started-services");
                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                    "Raise procstate to started service: " + app);
                        }
                    }
    
                    // hasShownUi只要该进程有onStartActivity的操作,就会设置成true,不管activity是否destroy,只要进程还在都是true
                    // 因为activity启动后默认是带有UI属性的:hasShownUi为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.
                        if (adj > ProcessList.SERVICE_ADJ) {
                            state.setAdjType("cch-started-ui-services");
                        }
                    } else {
                        // 1.lastActivity用于记录服务最后一次活动的时间戳
                        // 2.当服务被启动或绑定时,系统会更新lastActivity的值,以表示服务的最新活动时间
                        // 3.系统会定期检查服务的lastActivity值,如果服务长时间没有活动,系统就会认为该服务已经不再需要,自动停止该服务
                        // 4.now < lastActivity的值(服务最后活跃的时间戳)+30分钟,也就是lastActivity服务启动或者bind时间在30分钟以内
                        // ,因为服务启动和bind都会更新lastActivity值
                        // 5.那为什么是30分钟呢:解释如下-->
                        // MAX_SERVICE_INACTIVITY是一个常量,用于定义服务在没有activity的情况下可以保持运行的最长时间(activity销毁,服务还在,能存活的最大时间)
                        // 具体来说,它表示服务在没有任何客户端绑定或调用它的情况下可以保持运行的最长时间,超过这个时间,系统将自动停止该服务以释放系统资源
                        if (s.mKeepWarming
                                || now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY/*30分钟*/)) {
                            // This service has seen some activity within
                            // recent memory, so we will keep its process ahead
                            // of the background processes.
                            // 此服务在最近的内存中存在一些activity,因此我们将使其进程领先于后台进程
                            // service的对端存在activity,故调整服务adj为SERVICE_ADJ
                            if (adj > ProcessList.SERVICE_ADJ) {
                                adj = ProcessList.SERVICE_ADJ;
                                state.setAdjType("started-services");
                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                            "Raise adj to started service: " + app);
                                }
                                state.setCached(false);
                            }
                        }
                        // If we have let the service slide into the background
                        // state, still have some text describing what it is doing
                        // even though the service no longer has an impact.
                        if (adj > ProcessList.SERVICE_ADJ) {
                            state.setAdjType("cch-started-services");
                        }
                    }
                }
    
                // 如果是前台服务
                if (s.isForeground) {
                    // foregroundServiceType一般是AndroidManifest中设置,代表着前台服务type,所拥有哪些能力
                    // 例如:android:foregroundServiceType="dataSync|mediaPlayback|phoneCall|location|connectedDevice"
                    final int fgsType = s.foregroundServiceType;
                    // 是否允许前台服务中的使用权限
                    if (s.mAllowWhileInUsePermissionInFgs) {
                        // 拥有前台权限的位置信息
                        capabilityFromFGS |=
                                (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
                                        != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
    
                        final boolean enabled = state.getCachedCompatChange(
                                CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY);
                        if (enabled) {
                            // 拥有前台权限的相机调用
                            capabilityFromFGS |=
                                    (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
                                            != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0;
                            // 拥有前台权限的麦克风使用
                            capabilityFromFGS |=
                                    (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
                                            != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0;
                        } else {
                            // 如果是版本过低,这默认将camera、听筒的权限赋值给前台服务
                            capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
                                    | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
                        }
                    }
                }
    
                ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
                // 获取service中对应的所有连接,也就是bindService中的连接对象
                // 遍历所有的服务,ArrayMap是按照key的hashCode/identityHashCode进行排序的,不是按照add进去的时间进行排序
                // 这里是从serviceConnections尾部向头部遍历
                // 如果当前进程的adj > 0或者进程分组schedGroup是后台或者进程状态 > top,才进行调整(adj低的不进行依赖调整,减少调整次数)
                for (int conni = serviceConnections.size() - 1;
                        conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                                || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                                || procState > PROCESS_STATE_TOP);
                        conni--) {
                    // 获取service的连接对象ConnectionRecord,这里是list,因为一个服务可能会被绑定(连接)多次
                    ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
                    // 只调整adj > 前台app,处于后台分组,或者进程状态非top,这三个条件的意思就是:非前台的都进行调整,进入此case
                    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.
                        // 应根据所有连接客户端的adj最大值来计算此值
                        // 获取单个连接
                        ConnectionRecord cr = clist.get(i);
                        // cr.binding.client代表着谁启动的该服务
                        // 如果服务链接的客户端是当前app,则跳过,客户端的adj不会由于服务端的adj提升而升高---但服务端的adj受客户端app的影响
                        // 只有服务端的adj,才会由于客户端的adj提升而得到相应的提升(不然会出现客户端在使用的时候服务端由于优先级低给回收掉了)
                        if (cr.binding.client == app) {
                            // 获取了所有运行的服务,发现该服务的客户端是该app,则不处理
                            // Binding to oneself is not interesting.
                            continue;
                        }
    
                        // 通过mProcessStats.mTrackingAssociations.add(this);将其放入记录ProcessState列表中
                        // 在updateOomAdjInnerLSP的updateTrackingAssociationsLocked会去更新这些add进去的进程状态
                        // data/system/procstats里面有保存相关数据
                        boolean trackedProcState = false;
    
                        // 获取service对端的客户端
                        ProcessRecord client = cr.binding.client;
                        // 客户端的进程状态
                        final ProcessStateRecord cstate = client.mState;
                        // 递归调用一次,computeClients是否需要计算当前进程的时候并计算服务、provider提供者对端client的adj
                        // 也就是当前正在处理服务的adj,同时去调整服务对端的客户端client的adj
                        if (computeClients) {
                            computeOomAdjLSP(client/*传入了客户端的app*/, cachedAdj, topApp, doingAll, now,
                                    cycleReEval, true);
                        } else {
                            // 否则直接设置客户端的原始adj和原始进程状态
                            cstate.setCurRawAdj(cstate.getCurAdj());
                            cstate.setCurRawProcState(cstate.getCurProcState());
                        }
    
                        // 获取客户端的原始adj和进程状态
                        int clientAdj = cstate.getCurRawAdj();
                        int clientProcState = cstate.getCurRawProcState();
    
                        // 如果客户端属于系统进程
                        final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
    
                        // 如果客户端不会被冻结,那么该app端(服务端所在进程)也不会被冻结---则服务端也被设置不允许冻结
                        if (client.mOptRecord.shouldNotFreeze()) {
                            // Propagate the shouldNotFreeze flag down the bindings.
                            app.mOptRecord.setShouldNotFreeze(true);
                        }
    
                        // bindService的特有标志,不影响 Service 进程的优先级的情况下,允许 Service 进程被加入后台队列中
                        if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
                            // 判断客户端adj是否计算完成,也就是如果cycleReEval为真,则设置为循环依赖计算
                            // 判断客户端是否具有循环计算,若循环计算中getCompletedAdjSeq还未达到预期,则返回true,跳过此次,进入下一次继续计算
                            if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                                continue;
                            }
    
                            // 如果包含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) {
                                // 如果属于前台服务
                                if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                                    // 如果客户端在属于前台服务的情况,必须带有BIND_BYPASS_POWER_NETWORK_RESTRICTIONS,才会赋予网络能力
                                    if ((cr.flags & Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)
                                            != 0) {
                                        capability |= PROCESS_CAPABILITY_NETWORK;
                                    }
                                } else {
                                    // 如果客户端不属于前台服务,则默认给网络能力
                                    capability |= PROCESS_CAPABILITY_NETWORK;
                                }
                            }
    
                            // 如果客户端的进程状态,比cache activity 还大,有可能是Empty,或进程不存在状态
                            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.
                                // 如果其他应用程序由于任何原因被缓存,出于这里的目的,我们将认为它是空的。除非在特定条件下,否则特定的缓存状态不会传播。
                                // 直接赋予empty
                                clientProcState = PROCESS_STATE_CACHED_EMPTY;
                            }
                            String adjType = null;
                            // BIND_ALLOW_OOM_MANAGEMENT:允许服务所在的进程进行正常的内存管理。它将被视为一个正在运行的服务,
                            // 允许系统在内存不足或其他突发奇想的情况下(暂时)删除进程,并在长时间运行时更积极地使其成为被杀死(并重新启动)的候选者
                            // 也就是更容易被杀死:允许内存管理系统管理 Service 的进程,允许系统在内存不足的时候删除这个进程
                            if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                                // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
                                // 设置不被冻结
                                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.
                                // 如果有ui---例如activity,且不是home进程
                                if (state.hasShownUi() && !state.getCachedIsHomeProcess()) {
                                    // If this process has shown some UI, let it immediately
                                    // go to the LRU list because it may be pretty heavy with
                                    // UI stuff.  We'll tag it with a label just to help
                                    // debug and understand what is going on.
                                    if (adj > clientAdj) {
                                        adjType = "cch-bound-ui-services";
                                    }
                                    state.setCached(false);
                                    // 设置客户端adj和服务端adj一样
                                    clientAdj = adj;
                                    clientProcState = procState;
                                } else {
                                    // 如果service最后活跃的时间在30分钟内
                                    if (now >= (s.lastActivity
                                            + mConstants.MAX_SERVICE_INACTIVITY)) {
                                        // This service has not seen activity within
                                        // recent memory, so allow it to drop to the
                                        // LRU list if there is no other reason to keep
                                        // it around.  We'll also tag it with a label just
                                        // to help debug and undertand what is going on.
                                        if (adj > clientAdj) {
                                            adjType = "cch-bound-services";
                                        }
                                        clientAdj = adj;
                                    }
                                }
                            }
                            // 如果服务端adj > 客户端adj,也就是客户端比服务端更为重要
                            if (adj > clientAdj) {
                                // If this process has recently shown UI, and
                                // the process that is binding to it is less
                                // important than being visible, then we don't
                                // care about the binding as much as we care
                                // about letting this process get into the LRU
                                // list to be killed and restarted if needed for
                                // memory.
                                // 如果存在ui,不是home进程,客户端adj > 可感知adj,服务端adj >= 900优先级
                                if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                                        && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                    if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
                                        adjType = "cch-bound-ui-services";
                                    }
                                } else {
                                    int newAdj;
                                    // 如果服务连接时里面包含BIND_ABOVE_CLIENT或者BIND_IMPORTANT的时候
                                    // BIND_ABOVE_CLIENT: 代表服务的优先级需要比客户端client的高
                                    // BIND_IMPORTANT:代表此服务很重要,adj可以到0(fg)或者-700(PERSISTENT_SERVICE)
                                    // 而一般情况下,客户端属于前台,服务端会处于可见adj
                                    if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                            |Context.BIND_IMPORTANT)) != 0) {
                                        // 如果>=常驻服务adj,则客户端和服务端保持一致adj
                                        if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
                                            newAdj = clientAdj;
                                        } else {
                                            // 如果客户端adj < PERSISTENT_SERVICE_ADJ,那至少都是常驻进程
                                            // 将服务端设置为常驻服务,设置默认分组,进程状态也是常驻state
                                            // make this service persistent
                                            newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
                                            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                            procState = ActivityManager.PROCESS_STATE_PERSISTENT;
                                            cr.trackProcState(procState, mAdjSeq, now);
                                            trackedProcState = true;
                                        }
                                        // 如果是不可感知服务 且客户端比服务端优先级更低的情况:客户端adj <= 可感知adj。服务端adj >= 最低可感知adj
                                    } else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0
                                            && clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
                                            && adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                                        // 则服务端adj赋予最低可感知adj(250)
                                        newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
                                        // 如果服务端带有BIND_ALMOST_PERCEPTIBLE:允许服务端所在进程被视为对用户来说就像一个可感知的应用程序一样重要,
                                        // 并避免oom杀手在内存不足的情况下杀死这个进程,也是提高服务端进程优先级
                                        // 且客户端adj < 可感知,服务端adj >= 媒体音乐可感知,也就是客户端比服务端adj更底的情况
                                    } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0
                                            && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                            && adj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
                                        // 也就是客户端比服务端adj更底的情况,调整服务端adj为PERCEPTIBLE_MEDIUM_APP_ADJ
                                        newAdj = ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
                                        // 如果服务端不可见,且客户端<可感知 ,服务端 >= 可感知
                                    } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                            && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                            && adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
                                        // 也就是客户端比服务端adj更底的情况,则服务端默认也给到PERCEPTIBLE_APP_ADJ
                                        newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                    } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {// 如果客户端大于等于可感知adj,则服务端和客户端adj保持一致
                                        newAdj = clientAdj;
                                    } else {
                                        // 服务端大于VISIBLE_APP_ADJ(100),则从clientAdj和VISIBLE_APP_ADJ取一个最大值
                                        // 大概情况也就是从可感知adj(200~250)和可见adj(100)选一个
                                        if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                            // TODO: Is this too limiting for apps bound from TOP?
                                            newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
                                        } else {
                                            // 反之不做调整
                                            newAdj = adj;
                                        }
                                    }
                                    if (!cstate.isCached()) {
                                        state.setCached(false);
                                    }
                                    // 如果重新计算过后的newAdj比adj要小,说明进程优先级被拉低了,更容易保活,调整有效
                                    if (adj >  newAdj) {
                                        // 赋值给adj
                                        adj = newAdj;
                                        state.setCurRawAdj(adj);
                                        adjType = "service";
                                    }
                                }
                            }
                            // 如果服务端没有设置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();
                                // 如果客户端分组大于服务端分组,分组越大,能力越强
                                if (curSchedGroup > schedGroup) {
                                    // 在服务端分组能力比客户端分组能力弱的情况,且服务端还带有重要进程flag
                                    // 则将客户端分组能力分配给服务端
                                    if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                                        schedGroup = curSchedGroup;
                                    } else {
                                        // 反之服务端分组到默认(2)
                                        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)) {
                                        // 客户端进程状态改为:绑定前台服务,也就是服务端带有BIND_FOREGROUND_SERVICE,影响到了客户端的进程状态
                                        clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                                        state.bumpAllowStartFgsState(
                                                PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
                                        // 如果处于亮屏 且 带有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;
                                    } else {
                                        // 反之客户端进程状态改为重要的前台
                                        clientProcState =
                                                PROCESS_STATE_IMPORTANT_FOREGROUND;
                                    }
                                    // 如果客户端进程状态处于TOP(2)
                                } else if (clientProcState == PROCESS_STATE_TOP) {
                                    // Go at most to BOUND_TOP, unless requested to elevate
                                    // to client's state.
                                    // 客户端进程状态降低一档,到PROCESS_STATE_BOUND_TOP(3)
                                    clientProcState = PROCESS_STATE_BOUND_TOP;
                                    state.bumpAllowStartFgsState(PROCESS_STATE_BOUND_TOP);
                                    // sdk判断
                                    final boolean enabled = cstate.getCachedCompatChange(
                                            CACHED_COMPAT_CHANGE_PROCESS_CAPABILITY);
                                    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.
                                        capability |= cstate.getCurCapability();
                                    }
                                }
                                // 如果服务端不具有重要的后台flag
                            } else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
                                // 则将客户端进程状态设置为短暂后台状态
                                if (clientProcState <
                                        PROCESS_STATE_TRANSIENT_BACKGROUND) {
                                    clientProcState =
                                            PROCESS_STATE_TRANSIENT_BACKGROUND;
                                }
                            } else {
                                // 如果具有重要的后台服务flag,并且客户端进程状态也要低于PROCESS_STATE_IMPORTANT_BACKGROUND
                                // 才会将客户端进程状态设置为PROCESS_STATE_IMPORTANT_BACKGROUND
                                // 如果满足条件,算是变相把客户端进程优先级拉高了,算个调整策略
                                if (clientProcState <
                                        PROCESS_STATE_IMPORTANT_BACKGROUND) {
                                    clientProcState =
                                            PROCESS_STATE_IMPORTANT_BACKGROUND;
                                }
                            }
    
                            // 如果服务端分组< top,可能是默认default分组
                            // 且带有SCHEDULE_LIKE_TOP_APP:像对待top app那样对待服务
                            // 且客户端是系统服务
                            if (schedGroup < ProcessList.SCHED_GROUP_TOP_APP
                                    && (cr.flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0
                                    && clientIsSystem) {
                                // 则直接将服务端的分组调整到第二高
                                schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                                scheduleLikeTopApp = true;
                            }
    
                            if (!trackedProcState) {
                                cr.trackProcState(clientProcState, mAdjSeq, now);
                            }
    
                            // 如果服务进程状态 > 客户端进程状态,很正常,服务端都要比客户端状态要高,顶天只能相等
                            // 将客户端进程状态赋值给服务端进程状态
                            if (procState > clientProcState) {
                                procState = clientProcState;
                                state.setCurRawProcState(procState);
                                if (adjType == null) {
                                    adjType = "service";
                                }
                            }
                            // 如果进程状态 < PROCESS_STATE_IMPORTANT_BACKGROUND,说明至少是个重要的前台进程
                            // 且带有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);
                            }
                            // 设置此次优先级调整时,记录谁调整了adj,根据谁调整的adj,源头和target是谁
                            if (adjType != null) {
                                state.setAdjType(adjType);
                                state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                        .REASON_SERVICE_IN_USE);
                                // setAdjSource设置此次调整的来源:客户端ProcessRecord
                                state.setAdjSource(cr.binding.client);
                                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));
                                }
                            }
                        } else { // BIND_WAIVE_PRIORITY == true,代表不影响 Service 进程的优先级的情况下,允许 Service 进程被加入后台队列中
                            // BIND_WAIVE_PRIORITY bindings are special when it comes to the
                            // freezer. Processes bound via WPRI are expected to be running,
                            // but they are not promoted in the LRU list to keep them out of
                            // cached. As a result, they can freeze based on oom_adj alone.
                            // Normally, bindToDeath would fire when a cached app would die
                            // in the background, but nothing will fire when a running process
                            // pings a frozen process. Accordingly, any cached app that is
                            // bound by an unfrozen app via a WPRI binding has to remain
                            // unfrozen.
                            // 设置服务端不被冻结
                            if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
                                app.mOptRecord.setShouldNotFreeze(true);
                            }
                        }
                        // 服务端psr则设置setTreatLikeActivity的标记位,需要像对待activity一样对待该服务进程
                        if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                            psr.setTreatLikeActivity(true);
                        }
                        // 获取客户端对象的activity
                        final ActivityServiceConnectionsHolder a = cr.activity;
                        // 如果从一个 Activity 绑定,则这个 Service 进程的优先级和 Activity 是否对用户可见有关
                        // 简言之:可以根据客户端activity是否可见来调整优先级
                        if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
                            // activity > 前台app(0)(即activity非前台的情况--可能是recent的top app,或者可感知activity)
                            // ,一般activity处于前台时,adj都为0,处于后台时,一般是700
                            // 简言之这个条件:activity非前台,但是具有可见性质
                            if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ
                                    && a.isActivityVisible()) {
                                // 服务端调整到可见状态
                                adj = ProcessList.FOREGROUND_APP_ADJ;
                                // 设置服务端的原始adj
                                state.setCurRawAdj(adj);
                                // 如果服务端非前台
                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                                    // 但是服务端处于重要的后台,则将分组分配到最高(4)
                                    if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                                        schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
                                    } else {
                                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                    }
                                }
                                // 因为客户端activity可见,再次设置adj type
                                state.setCached(false);
                                state.setAdjType("service");
                                state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                        .REASON_SERVICE_IN_USE);
                                state.setAdjSource(a);
                                state.setAdjSourceProcState(procState);
                                state.setAdjTarget(s.instanceName);
                                if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                    reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                            "Raise to service w/activity: " + app);
                                }
                            }
                        }
                    }
                }
            }
    
            // 开始处理contentProvider优先级
            final ProcessProviderRecord ppr = app.mProviders;
            // 遍历该进程的所有contentProvider
            for (int provi = ppr.numberOfProviders() - 1;
                    provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                            || procState > PROCESS_STATE_TOP);
                    provi--) {
                // 获取ContentProvider
                ContentProviderRecord cpr = ppr.getProviderAt(provi);
                // 遍历所有连接了该ContentProvider的连接对象
                for (int i = cpr.connections.size() - 1;
                        i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                                || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                                || procState > PROCESS_STATE_TOP);
                        i--) {
                    // ContentProvider连接对象
                    ContentProviderConnection conn = cpr.connections.get(i);
                    // 因为连接的话,都是在客户端发起连接的,这里获取客户端的ProcessRecord
                    ProcessRecord client = conn.client;
                    // 客户端的进程状态
                    final ProcessStateRecord cstate = client.mState;
                    // 如果处于同个进程,不做调整
                    if (client == app) {
                        // Being our own client is not interesting.
                        continue;
                    }
                    // 是否带有循环计算标志
                    if (computeClients) {
                        computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
                    } else {
                        // 如果没有,客户端原始的adj设置为约束过后的adj
                        cstate.setCurRawAdj(cstate.getCurAdj());
                        cstate.setCurRawProcState(cstate.getCurProcState());
                    }
    
                    if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                        continue;
                    }
    
                    // 获取客户端原始的adj,经过上面的步骤,获取的其实是被约束过后的adj
                    int clientAdj = cstate.getCurRawAdj();
                    int clientProcState = cstate.getCurRawProcState();
    
                    // 客户端如果处于cached状态,则默认给到empty
                    if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                        // If the other app is cached for any reason, for purposes here
                        // we are going to consider it empty.
                        clientProcState = PROCESS_STATE_CACHED_EMPTY;
                    }
                    // 如果客户端应该不会被冻结,那么服务端也会被设置为不被冻结
                    if (client.mOptRecord.shouldNotFreeze()) {
                        // Propagate the shouldNotFreeze flag down the bindings.
                        app.mOptRecord.setShouldNotFreeze(true);
                    }
                    String adjType = null;
                    // 服务端adj比客户端adj大,再正常不过了
                    if (adj > clientAdj) {
                        // 如果该进程有界面的,而且不是桌面,而且客户端clientAdj大于200,这类不调整adj大小,只设置adj类型
                        if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                                && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                            adjType = "cch-ui-provider";
                        } else {// 反之客户端如果大于前台app,则服务端默认使用前台adj,如果客户端小于等于前台adj,则服务端也调整到前台adj
                            adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                                    ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
                            state.setCurRawAdj(adj);
                            adjType = "provider";
                        }
                        state.setCached(state.isCached() & cstate.isCached());
                    }
    
                    // 如果客户端进程状态 <= 前台服务
                    if (clientProcState <= PROCESS_STATE_FOREGROUND_SERVICE) {
                        if (adjType == null) {
                            adjType = "provider";
                        }
                        // 客户端进程状态在top状态,则默认调低一档到PROCESS_STATE_BOUND_TOP
                        if (clientProcState == PROCESS_STATE_TOP) {
                            clientProcState = PROCESS_STATE_BOUND_TOP;
                        } else {// 反之调整到BOUND_FOREGROUND_SERVICE(5),绑定前台服务
                            clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                        }
                    }
    
                    conn.trackProcState(clientProcState, mAdjSeq, now);
                    // 如果服务端进程状态 > 客户端进程状态,则服务端跟客户端保持一致
                    if (procState > clientProcState) {
                        procState = clientProcState;
                        // 设置原始的进程状态
                        state.setCurRawProcState(procState);
                    }
                    // 如果客户端分组大于服务端分组,则将服务端分组设置为默认
                    if (cstate.getCurrentSchedulingGroup() > schedGroup) {
                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                    }
                    if (adjType != null) {
                        state.setAdjType(adjType);
                        state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                .REASON_PROVIDER_IN_USE);
                        state.setAdjSource(client);
                        state.setAdjSourceProcState(clientProcState);
                        state.setAdjTarget(cpr.name);
                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                            reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                    + ": " + app + ", due to " + client
                                    + " adj=" + adj + " procState="
                                    + ProcessList.makeProcStateString(procState));
                        }
                    }
                }
                // If the provider has external (non-framework) process
                // dependencies, ensure that its adjustment is at least
                // FOREGROUND_APP_ADJ.
                // 如果ContentProvider具有外部(非框架)进程依赖关系,请确保其调整至少为FOREGROUND_APP_ADJ
                if (cpr.hasExternalProcessHandles()) {
                    if (adj > ProcessList.FOREGROUND_APP_ADJ) {
                        adj = ProcessList.FOREGROUND_APP_ADJ;
                        state.setCurRawAdj(adj);
                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                        state.setCached(false);
                        state.setAdjType("ext-provider");
                        state.setAdjTarget(cpr.name);
                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                    "Raise adj to external provider: " + app);
                        }
                    }
                    if (procState > PROCESS_STATE_IMPORTANT_FOREGROUND) {
                        procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
                        state.setCurRawProcState(procState);
                        if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                            reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                    "Raise procstate to external provider: " + app);
                        }
                    }
                }
            }
    
            // 以上ContentProvider就调整完成了
            // 大概意思是provider上一次使用的时间,设置了这个时间的话provider会延迟一小会释放(kill),
            // CONTENT_PROVIDER_RETAIN_TIME是20s,上一次使用在20s以内会进来这里,避免低内存状态下频繁启动回收provider进程
            if (ppr.getLastProviderTime() > 0
                    && (ppr.getLastProviderTime() + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
                // 设置为700的优先级,也就是后台情况
                if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                    adj = ProcessList.PREVIOUS_APP_ADJ;
                    // 设置后台分组
                    schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                    state.setCached(false);
                    state.setAdjType("recent-provider");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise adj to recent provider: " + app);
                    }
                }
                // 设置为最后显示activity的进程状态
                if (procState > PROCESS_STATE_LAST_ACTIVITY) {
                    procState = PROCESS_STATE_LAST_ACTIVITY;
                    state.setAdjType("recent-provider");
                    if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                        reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                "Raise procstate to recent provider: " + app);
                    }
                }
            }
    
            // 如果服务端是empty,但是客户端存在activity,将服务端进程状态调整为PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
            // 缓存进程,缓存了activity信息
            if (procState >= PROCESS_STATE_CACHED_EMPTY) {
                if (psr.hasClientActivities()) {
                    // This is a cached process, but with client activities.  Mark it so.
                    procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
                    state.setAdjType("cch-client-act");
                } else if (psr.isTreatedLikeActivity()) {// 如果服务端看起来向activity,像对待activity那样对待该进程
                    // This is a cached process, but somebody wants us to treat it like it has
                    // an activity, okay!
                    // 稍微提升一点优先级
                    procState = PROCESS_STATE_CACHED_ACTIVITY;
                    state.setAdjType("cch-as-act");
                }
            }
    
            // 如果服务端adj处于(500),只有上一次lastActivity服务启动或者bind时间是30分钟以内的才会设置成SERVICE_ADJ级别
            if (adj == ProcessList.SERVICE_ADJ) {
                // 调整A/B服务
                if (doingAll && !cycleReEval) {
                    // 当A服务数量 > 服务个数 / 3 时,也就是1/3的服务会被设置成B services
                    state.setServiceB(mNewNumAServiceProcs > (mNumServiceProcs / 3));
                    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获取是内存压力级别 ,返回false,代表此时有内存压力
                        // getCachedRestoreThresholdKb,如果是32bit是184320/3 = 60M, 64bit是322560/3=105M,具体逻辑在ProcessList.java中
                        // 也就是进程的mLastPss大于60M(32bit)/105M(64bit),
                        // 而且是有内存压力的时候会将这类服务标记成高内存用量,而且回落到B serviceB
                        if (!mService.mAppProfiler.isLastMemoryLevelNormal()
                                && app.mProfile.getLastPss()
                                >= mProcessList.getCachedRestoreThresholdKb()) {
                            state.setServiceHighRam(true);
                            // 从A回落到B
                            state.setServiceB(true);
                            //Slog.i(TAG, "ADJ " + app + " high ram!");
                        } else {
                            mNewNumAServiceProcs++;
                            //Slog.i(TAG, "ADJ " + app + " not high ram!");
                        }
                    } else {
                        // 反之设置为该服务没有内存压力,没有高用量内存(B服务没有高用量)
                        state.setServiceHighRam(false);
                    }
                }
                // 如果是服务B,则adj设置为SERVICE_B_ADJ(800):这些都是老旧的服务,没有A列表中的那么闪亮和有趣
                if (state.isServiceB()) {
                    adj = ProcessList.SERVICE_B_ADJ;
                }
            }
    
            state.setCurRawAdj(adj);
    
            // 服务端adj如果大于了设置的最大adj,则默认使用最大adj
            // 最大不能超过getMaxAdj
            if (adj > state.getMaxAdj()) {
                adj = state.getMaxAdj();
                if (adj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                }
            }
    
            // Put bound foreground services in a special sched group for additional
            // restrictions on screen off
            // 如果灭屏状态且不像是activity,分组到SCHED_GROUP_RESTRICTED
            if (procState >= PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                    && mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
                    && !scheduleLikeTopApp) {
                if (schedGroup > ProcessList.SCHED_GROUP_RESTRICTED) {
                    schedGroup = ProcessList.SCHED_GROUP_RESTRICTED;
                }
            }
    
            // apply capability from FGS.
            // 进程是前台服务,则将当前进程的能力capability设置成前台服务的能力capabilityFromFGS
            if (psr.hasForegroundServices()) {
                capability |= capabilityFromFGS;
            }
    
            // 通过进程状态,如果进程状态是常驻进程或者top级别,则拥有全部能力
            // 如果进程状态是PROCESS_STATE_BOUND_TOP,则只有网络能力
            // 如果进程状态是前台服务,则只能网络能力
            capability |= getDefaultCapability(psr, procState);
    
            // 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.
            // modifyRawOomAdj需要仔细分析,这里就是约束过的adj在复制给mCurAdj,而且一般都是adj调整完成后设置
            // 这里就算针对调整后的adj,再进行一次约束
            state.setCurAdj(psr.modifyRawOomAdj(adj));
            // 设置进程能力
            state.setCurCapability(capability);
            // 设置进程分组
            state.setCurrentSchedulingGroup(schedGroup);
            // 设置进程状态
            state.setCurProcState(procState);
            // 设置进程原始状态---未被约束的情况
            state.setCurRawProcState(procState);
            state.updateLastInvisibleTime(hasVisibleActivities);
            // 设置是否前台服务
            state.setHasForegroundActivities(foregroundActivities);
            // 设置此次的调整完成
            state.setCompletedAdjSeq(mAdjSeq);
    
            // if curAdj or curProcState improved, then this process was promoted
            // 只有adj调整到更底,或者进程状态调整到更底,或者能力变更了才返回true
            // 如果adj调整到更高,则返回false,但也是调整了的
            return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
                    || state.getCurCapability() != prevCapability;
        }
    
    • 四大组件部分

    • 服务端(Service)与客户端部分

      什么时候客户端adj会根据服务端调整?拥有BIND_ALLOW_OOM_MANAGEMENT的时候会被调整

      什么时候客户端进程状态会根据服务端调整?客户端进程状态 < PROCESS_STATE_TOP的时候,会根据是否具有前台服务,赋予STATE_BOUND_FORCESERVICE状态,如果没有前台服务,则会赋予PROCESS_STATE_IMPORTANT_FOREGROUND—-第10点和第11点

    • 服务端(ContentProvider)与客户端部分

  • applyOomAdjLSP

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android内存机制在不同版本之间有着较大的演变,其中最主要的就是内存管理策略的变化。在早期的Android版本中,内存管理采用的是进程优先级的方式,即根据进程的重要性和消耗的资源量来确定内存使用的权重,但这种方式容易导致内存不足的情况,进而导致应用程序崩溃。 后来,Google在Android 2.0中引入了LowMemoryKiller机制,通过监控系统内存使用情况,当内存不足时自动清理不必要的进程,以释放内存资源。LowMemoryKiller机制的实现是通过kernel的oom-killer机制来实现的,当系统内存不足时,通过oom_adj值来判断哪些进程可以杀掉,以释放内存资源。在Android 2.x中,LowMemoryKiller机制主要依赖于进程oom_adj值的设置,以及进程的重要性和消耗的资源量来判断哪些进程可以被杀掉。 随着Android版本的不断升级,Google也对LowMemoryKiller机制进行了多次优化,主要包括: 1. Android 3.0中引入了memcg机制,通过将进程的内存资源划分为多个cgroup,实现对内存资源的精细化管理。 2. Android 4.0中引入了Lmkd机制,通过对进程的内存资源进行动态调整,以更加精准地释放内存资源。 3. Android 4.4中引入了Zram机制,通过将一部分物理内存作为压缩内存使用,提高内存使用效率。 4. Android 6.0中引入了Doze机制,通过限制应用程序的后台运行,以降低系统内存负载。 总的来说,Android的内存管理机制是不断演变和优化的过程,不断追求更加高效和精细化的内存管理方式,以保证系统的稳定性和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值