为您推荐:
精华内容
最热下载
问答
  • 5星
    1.64MB weixin_41581125 2021-02-04 09:34:48
  • 一、oom_adj 值对应的进程优先级、 二、oom_adj 值动态改变、 1、正常运行时的 oom_adj 值、 2、按下 Home 键后的 oom_adj 值、 3、按下回退键后的 oom_adj 值、 二、进程保活优化方向、





    一、oom_adj 值对应的进程优先级



    oom_adj 值对应的进程优先级 : 优先级从上到下越来越高 , 最下面的优先级最高 , 最上面的优先级最低 ;

    • UNKNOWN_ADJ = 16 : 缓存进程 ;
    • CACHED_APP_MAX_ADJ = 15 : 不可见进程的 oom_adj 最大值 ;
    • CACHED_APP_MIN_ADJ = 9 : 不可见进程的 oom_adj 最小值 ;
    • SERVICE_B_ADJ = 8 : 在 B 列表中的 Service 服务 , 这些服务比较老 , 再次使用的可能性较小 ;
    • PREVIOUS_APP_ADJ = 7 : 上一个应用程序进程 , 即上一次按下返回键退出的应用 , 缓存应用中的第一个应用 ;
    • HOME_APP_ADJ = 6 : Home 应用所在的进程 , 不能杀 ;
    • SERVICE_ADJ = 5 : 服务进程 ;
    • HEAVY_WEIGHT_APP_ADJ = 4 : 后台的重量级继承 , 启动时在 system/rootdir/init.rc 配置中设置 ;

    • BACKUP_APP_ADJ = 3 : 进入后台的进程 , 按下 Menu 键可查看 , 备份进程 , 可唤醒 ;
    • PERCEPTIBLE_APP_ADJ = 2 : 可感知进程 , 如后台播放音乐 , 铃声 , 震动 , 闪光灯 等除视觉外的其它可感知效果 ;
    • VISIBLE_APP_ADJ = 1 : 可见进程 ;
    • FOREGROUND_APP_ADJ = 0 : 前台进程 ;

    • PERSISTENT_SERVICE_ADJ = -11 : 系统或持久化进程绑定的进程 ;
    • PERSISTENT_PROC_ADJ = -12 : 系统持久化进程 , 如电话进程 ;
    • SYSTEM_ADJ = -16 : 系统进程 ;
    • NATIVE_ADJ = -17 : 本地进程 , 不受系统控制 ;

    打印出来的值是上述值 , 不是常量中定义的值 ;


    这些 ADJ 值都在 frameworks/base/services/core/java/com/android/server/am/ProcessList.java 源码中以常量形式记录 :

    /**
     * Activity manager code dealing with processes.
     */
    public final class ProcessList {
    
        // The B list of SERVICE_ADJ -- these are the old and decrepit
        // services that aren't as shiny and interesting as the ones in the A list.
        static final int SERVICE_B_ADJ = 800;
    
        // This is the process of the previous application that the user was in.
        // This process is kept above other things, because it is very common to
        // switch back to the previous app.  This is important both for recent
        // task switch (toggling between the two top recent apps) as well as normal
        // UI flow such as clicking on a URI in the e-mail app to view in the browser,
        // and then pressing back to return to e-mail.
        static final int PREVIOUS_APP_ADJ = 700;
    
        // This is a process holding the home application -- we want to try
        // avoiding killing it, even if it would normally be in the background,
        // because the user interacts with it so much.
        static final int HOME_APP_ADJ = 600;
    
        // This is a process holding an application service -- killing it will not
        // have much of an impact as far as the user is concerned.
        static final int SERVICE_ADJ = 500;
    
        // This is a process with a heavy-weight application.  It is in the
        // background, but we want to try to avoid killing it.  Value set in
        // system/rootdir/init.rc on startup.
        static final int HEAVY_WEIGHT_APP_ADJ = 400;
    
        // Adjustment used in certain places where we don't know it yet.
        // (Generally this is something that is going to be cached, but we
        // don't know the exact value in the cached range to assign yet.)
        static final int UNKNOWN_ADJ = 1001;
    
        // This is a process only hosting activities that are not visible,
        // so it can be killed without any disruption.
        static final int CACHED_APP_MAX_ADJ = 906;
        static final int CACHED_APP_MIN_ADJ = 900;
    
    
        // This is a process currently hosting a backup operation.  Killing it
        // is not entirely fatal but is generally a bad idea.
        static final int BACKUP_APP_ADJ = 300;
    
        // This is a process currently hosting a backup operation.  Killing it
        // is not entirely fatal but is generally a bad idea.
        static final int BACKUP_APP_ADJ = 300;
    
        // This is a process only hosting components that are perceptible to the
        // user, and we really want to avoid killing them, but they are not
        // immediately visible. An example is background music playback.
        static final int PERCEPTIBLE_APP_ADJ = 200;
    
        // This is a process only hosting activities that are visible to the
        // user, so we'd prefer they don't disappear.
        static final int VISIBLE_APP_ADJ = 100;
    
        // This is the process running the current foreground app.  We'd really
        // rather not kill it!
        static final int FOREGROUND_APP_ADJ = 0;
    
        // This is a process that the system or a persistent process has bound to,
        // and indicated it is important.
        static final int PERSISTENT_SERVICE_ADJ = -700;
    
        // This is a system persistent process, such as telephony.  Definitely
        // don't want to kill it, but doing so is not completely fatal.
        static final int PERSISTENT_PROC_ADJ = -800;
    
        // The system process runs at the default adjustment.
        static final int SYSTEM_ADJ = -900;
    
        // Special code for native processes that are not being managed by the system (so
        // don't have an oom adj assigned by the system).
        static final int NATIVE_ADJ = -1000;
    
        // Memory pages are 4K.
        static final int PAGE_SIZE = 4*1024;
    
    }
    

    参考源码 : frameworks/base/services/core/java/com/android/server/am/ProcessList.java





    二、oom_adj 值动态改变





    1、正常运行时的 oom_adj 值


    一个程序的 oom_adj 值是不断动态改变的 , 当程序处于前台时 , 该前台进程的 oom_adj 的值为 0 ,

    运行程序 ,

    在这里插入图片描述

    在 Android Studio 中 , 可以看到该运行的程序的进程号 PID 为 30856 30856 30856 ,
    在这里插入图片描述

    进入 adb shell 命令行 , su 获取 root 权限 , 使用如下命令 , 查询指定 PID 的 oom_adj 值 ;

    cat /proc/30856/oom_adj
    

    在这里插入图片描述




    2、按下 Home 键后的 oom_adj 值


    点击 Home 键 , 程序退出 , 显示 Home 程序 ,

    在这里插入图片描述

    此时查询该 PID 为 30856 30856 30856 的 oom_adj 值为 12 12 12 , 不可见进程范围是 9 9 9 ~ 15 15 15 , 此时的状态是不可见状态 ;

    在这里插入图片描述




    3、按下回退键后的 oom_adj 值


    在这里插入图片描述

    如果是按下回退键退出界面 , 此时查询该 PID 为 30856 30856 30856 的 oom_adj 值为 16 16 16 , 此时进程的状态是缓存进程 , 随时都可能被杀掉 ;

    在这里插入图片描述





    二、进程保活优化方向



    优先级越高 , oom_adj 值越小 , 越不能被杀死 ;

    如果想要使得进程尽可能长的保留在内存中 , 那么就要减小 oom_adj 的值 ;

    在 oom_adj 值相同时 , 内存占用量越大的进程 , 被杀的几率就越高 , 因此这里还要尽可能降低进程占用尽可能少的内存 ;

    总结一下就是 ① 降低 oom_adj 值 , ② 减小内存占用 ;

    展开全文
    han1202012 2021-04-06 20:58:54
  • p-value是通过T检验产生的一个参数,它代表了两组样本之间的差异性。 一般来说,当p-value<0.05时,我们认为这两组样本差异显著。 一般情况下,看p-value即可判断样本差异性,但是事实情况并非如此。 有时候...

    p-value是通过T检验产生的一个参数,它代表了两组样本之间的差异性。

    一般来说,当p-value<0.05时,我们认为这两组样本差异显著。

    一般情况下,看p-value即可判断样本差异性,但是事实情况并非如此。

    有时候我们会在样本中发现许多0值,然后少量其它值,这种情况就会对p-value的可靠性造成影响,往往这种情况p-value会很显著,但很明显这样不符合现实。这种时候我们就需要对p-value进行校正,校正的流程这里不细说了,我们可以简单理解为,p-adjust是用来判断p-value是否可信的一个参数,它来自于p-value,但是相对于p-value可信度更高。这样我们就可以知道,在同时有p-value和p-adjust时,我们应该选择p-adjust用来作为显著性的阈值。

    q-value另有一些区别,它也来自于p-value。q-value可以简单理解为表示p-value产生假阳性的概率,当q-value < 0.05时,p-value显著的假阳性小于0.05。

    展开全文
    weixin_44070677 2021-09-15 00:06:46
  • 一,概述 提到进程调度,可能大家首先想到的是Linux cpu调度算法,进程优先级之类概念,此处并不打算介绍这些内容,而是介绍...进程有两个比较重要的状态值,即adj(定义在ProcessList.java)和procState(定义在A...

    一,概述

    提到进程调度,可能大家首先想到的是Linux cpu调度算法,进程优先级之类概念,此处并不打算介绍这些内容,而是介绍Android框架层中承载活动/服务/ contentprovider / broadcastrecevier的进程是如何根据组件运行状态而动态调节进程自身的状态。进程有两个比较重要的状态值,即adj(定义在ProcessList.java)和procState(定义在ActivityManager.java)。

    本文是根据android 6.0本机系统的算法分析,不同手机厂商都会有各自的激进策略。本文只介绍了Google本机系统adj和procState有某种程度。

    1.1调整

    定义在ProcessList.java文件中,oom_adj划分为16级,从17到16之间取值。adj 值变量,优先级越低,adj <0的进程都是系统进程。

    ADJ等级取值解释
    UNKNOWN_ADJ16一般指将要会缓存进程,无法获取确定值
    CACHED_APP_MAX_ADJ15不可见进展的adj预设
    CACHED_APP_MIN_ADJ9不可见进展的adj预设
    SERVICE_B_AD8B List中的服务(较老的,使用可能更小)
    PREVIOUS_APP_ADJ7上一个App的进程(经常通过按返回键)
    HOME_APP_ADJ6主页进程
    SERVICE_ADJ5服务进程(服务流程
    HEAVY_WEIGHT_APP_ADJ4后台的重量级进程,system / rootdir / init.rc文件中设置
    BACKUP_APP_ADJ3备份进程
    PERCEPTIBLE_APP_ADJ2可感知进展,某些后台音乐播放
    VISIBLE_APP_ADJ1个可见进程(可见过程
    FOREGROUND_APP_ADJ0前台进程(前台流程
    PERSISTENT_SERVICE_ADJ-11关联着系统或persistent进程
    PERSISTENT_PROC_ADJ-12系统persistent进程,某些电话
    SYSTEM_ADJ-16系统进展
    NATIVE_ADJ-17native进步(不被系统管理)

    lmkd会根据会根据当前系统可能的内存的情况,来决定杀掉不同的adj等级的进程,Android进程生命周期与ADJ

    FOREGROUND_APP_ADJ

    1.2 ProcessState

    定义在ActivityManager.java文件,process_state划分18类,从-1到16之间取值。

    国家等级取值解释
    PROCESS_STATE_CACHED_EMPTY16进度处于cached状态,且为空进度
    PROCESS_STATE_CACHED_ACTIVITY_CLIENT15进度处于cached状态,且为另一个cached进度(内含Activity)的客户端进度
    PROCESS_STATE_CACHED_ACTIVITY14进度处于cached状态,且内含活动
    PROCESS_STATE_LAST_ACTIVITY13后台进程,且拥有上一次显示的活动
    PROCESS_STATE_HOME12后台进程,且拥有home活​​动
    PROCESS_STATE_RECEIVER11后台进程,且正在运行接收器
    PROCESS_STATE_SERVICE10后台进程,且正在运行service
    PROCESS_STATE_HEAVY_WEIGHT9后台进程,但无法执行restore,因此尽量避免kill该进程
    PROCESS_STATE_BACKUP8后台进程,正在运行backup / restore操作
    PROCESS_STATE_IMPORTANT_BACKGROUND7对用户很重要的进程,用户不可感知其存在
    PROCESS_STATE_IMPORTANT_FOREGROUND6对用户很重要的进展,用户可感知其存在
    PROCESS_STATE_TOP_SLEEPING5与PROCESS_STATE_TOP一样,但此时设备正处于休眠状态
    PROCESS_STATE_FOREGROUND_SERVICE4拥有一个前台
    PROCESS_STATE_BOUND_FOREGROUND_SERVICE3拥有一个前台服务,且由系统绑定
    PROCESS_STATE_TOP2拥有当前用户可见的top活动
    PROCESS_STATE_PERSISTENT_UI1个persistent系统进程,并正在执行UI操作
    PROCESS_STATE_PERSISTENT0持续的系统进程
    PROCESS_STATE_NONEXISTENT-1不存在的进程

    1.3三大护法

    调整进程的adj的3大护法,也就是ADJ算法的核心方法:

    • updateOomAdjLocked:更新adj,当目标进程为空,或者被杀则返回false;否则返回true;
    • computeOomAdjLocked:计算adj,返回计算后RawAdj值;
    • applyOomAdjLocked:应用adj,当需要杀掉目标进程则返回false;否则返回true。

    前面提到调整adj的3大护法,最常见的方法便是updateOomAdjLocked,这也是其他多个方法在需要更新adj时会调用的方法,该方法有3个不同参数的同名方法,定义如下:

    <span style="color:#404040"><span style="color:#333333"><code>无参方法:updateOomAdjLocked()
    一参方法:updateOomAdjLocked(ProcessRecord app)
    五参方法:updateOomAdjLocked(ProcessRecord app, <span style="color:#cc7832">int</span> cachedAdj,
        ProcessRecord TOP_APP, <span style="color:#cc7832">boolean</span> doingAll, <span style="color:#cc7832">long</span> now)
    </code></span></span>

    updateOomAdjLocked实现过程中依次会computeOomAdjLockedapplyOomAdjLocked

    二。ADJ的更新时机

    先来说说什么场景下都会触发updateOomAdjLocked来更新进程adj:

    2.1活动

    • ASS.realStartActivityLocked:启动活动
    • AS.resumeTopActivityInnerLocked:恢复栈顶活动
    • AS.finishCurrentActivityLocked:结束当前活动
    • AS.destroyActivityLocked:破坏当前活动

    2.2服务

    位于ActiveServices.java

    • realStartServiceLocked:启动服务
    • bindServiceLocked:绑定服务(只更新当前应用)
    • unbindServiceLocked:解绑服务(只更新当前app)
    • BringDownServiceLocked:结束服务(只更新当前app)
    • sendServiceArgsLocked:在bringup或则cleanup服务过程调用(只更新当前app)

    2.3广播

    • BQ.processNextBroadcast:处理下一个广播
    • BQ.processCurBroadcastLocked:处理当前广播
    • BQ.deliverToRegisteredReceiverLocked:分发已注册的广播(只更新当前app)

    2.4 ContentProvider

    • AMS.removeContentProvider:可移除提供者
    • AMS.publishContentProviders:发布提供程序(仅更新当前应用)
    • AMS.getContentProviderImpl:获取提供程序(仅更新当前应用)

    2.5流程

    位于ActivityManagerService.java

    • setSystemProcess:创建并设置系统进程
    • addAppLocked:创建持久进程
    • attachApplicationLocked:逐步创建后attach到system_server的过程;
    • trimApplications:清除没有使用app
    • appDiedLocked:进展死亡
    • killAllBackgroundProcesses:杀死所有后台进程。即(ADJ> 9或removed = true的普通进程)
    • killPackageProcessesLocked:以包名的形式杀掉相关进程;

    三。updateOomAdjLocked

    3.1重要参数

    在介绍updateOomAdjLocked方法之前,先简单介绍这个过程会遇到的比较重要的参数。

    [-> ProcessList.java]

    • 空进程存活时长:MAX_EMPTY_TIME = 30分钟
    • (缓存+空)进程个数上限:MAX_CACHED_APPS= SystemProperties.getInt(“ sys.fw.bg_apps_limit”,32)= 32(最小);
    • 空进程个数上限:MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS)= MAX_CACHED_APPS / 2 = 16;
    • trim空进程个数上限:TRIM_EMPTY_APPS= computeTrimEmptyApps()= MAX_EMPTY_APPS / 2 = 8;
    • 修剪缓存进程个数上限:TRIM_CACHED_APPS= computeTrimCachedApps()= MAX_CACHED_APPS-MAX_EMPTY_APPS)/ 3 = 5;
    • TRIM_CRITICAL_THRESHOLD = 3;

    [-> AMS.java]

    • mBServiceAppThreshold = SystemProperties.getInt(“ ro.sys.fw.bservice_limit”,5);
    • mMinBServiceAgingTime = SystemProperties.getInt(“ ro.sys.fw.bservice_age”,5000);
    • mProcessLimit = ProcessList.MAX_CACHED_APPS
    • mProcessLimit = emptyProcessLimit(空进程上限)+ cachedProcessLimit(缓存进程上限)
    • oldTime =现在-ProcessList.MAX_EMPTY_TIME;
    • LRU进程队列长度 = numEmptyProcs(空进程数)+ mNumCachedHiddenProcs(cached进程)+ mNumNonCachedProcs(非缓存进程)
    • emptyFactor = numEmptyProcs / 3,且大于等于1
    • cachedFactor = mNumCachedHiddenProcs / 3,且大于等于1

    3.2一参方法

    [-> ActivityManagerService.java]

    <span style="color:#404040"><span style="color:#333333"><code><span style="color:#cc7832">final</span> <span style="color:#cc7832">boolean</span> <span style="color:#ffc66d">updateOomAdjLocked</span>(ProcessRecord app) {
        <span style="color:#808080">//获取栈顶的Activity</span>
        <span style="color:#cc7832">final</span> ActivityRecord TOP_ACT = resumedAppLocked();
        <span style="color:#cc7832">final</span> ProcessRecord TOP_APP = TOP_ACT != <span style="color:#cc7832">null</span> ? TOP_ACT.app : <span style="color:#cc7832">null</span>;
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">boolean</span> wasCached = app.cached;
    
        mAdjSeq++;
    
        <span style="color:#808080">//确保cachedAdj>=9</span>
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ
                ? app.curRawAdj : ProcessList.UNKNOWN_ADJ;
    
        <span style="color:#808080">//执行五参updateOomAdjLocked【见小节3.3】</span>
        <span style="color:#cc7832">boolean</span> success = updateOomAdjLocked(app, cachedAdj, TOP_APP, <span style="color:#cc7832">false</span>,
                SystemClock.uptimeMillis());
    
        <span style="color:#808080">//当app cached状态改变,或者curRawAdj=16,则执行无参数updateOomAdjLocked【见小节2.3】</span>
        <span style="color:#cc7832">if</span> (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ) {
            updateOomAdjLocked();
        }
        <span style="color:#cc7832">return</span> success;
    }
    </code></span></span>

    该方法主要功能:

    1. 执行五参updateOomAdjLocked
    2. 当app经过更新adj操作后,其cached状态改变(包括由cached变成非cached,或者非cached变成cached),或者curRawAdj = 16,则执行无参updateOomAdjLocked

    3.3五参方法

    <span style="color:#404040"><span style="color:#333333"><code><span style="color:#cc7832">private</span> <span style="color:#cc7832">final</span> <span style="color:#cc7832">boolean</span> <span style="color:#ffc66d">updateOomAdjLocked</span>(ProcessRecord app, <span style="color:#cc7832">int</span> cachedAdj, ProcessRecord TOP_APP, <span style="color:#cc7832">boolean</span> doingAll, <span style="color:#cc7832">long</span> now) {
        <span style="color:#cc7832">if</span> (app.thread == <span style="color:#cc7832">null</span>) {
            <span style="color:#cc7832">return</span> <span style="color:#cc7832">false</span>;
        }
        <span style="color:#808080">//【见小节4】</span>
        computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
    
        <span style="color:#808080">//【见小节5】</span>
        <span style="color:#cc7832">return</span> applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
    }
    </code></span></span>

    该方法是私有方法,只提供给一参无参的同名方法调用,系统中并没有其他地方调用。

    3.4无参方法(核心)

    <span style="color:#404040"><span style="color:#333333"><code><span style="color:#cc7832">final</span> <span style="color:#cc7832">void</span> <span style="color:#ffc66d">updateOomAdjLocked</span>() {
        <span style="color:#808080">//获取栈顶的Activity</span>
        <span style="color:#cc7832">final</span> ActivityRecord TOP_ACT = resumedAppLocked();
        <span style="color:#cc7832">final</span> ProcessRecord TOP_APP = TOP_ACT != <span style="color:#cc7832">null</span> ? TOP_ACT.app : <span style="color:#cc7832">null</span>;
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">long</span> now = SystemClock.uptimeMillis();
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">long</span> nowElapsed = SystemClock.elapsedRealtime();
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">long</span> oldTime = now - ProcessList.MAX_EMPTY_TIME;
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> N = mLruProcesses.size();
    
        <span style="color:#808080">//重置所有uid记录,把curProcState设置成16(空进程)</span>
        <span style="color:#cc7832">for</span> (<span style="color:#cc7832">int</span> i=mActiveUids.size()-<span style="color:#6897bb">1</span>; i>=<span style="color:#6897bb">0</span>; i--) {
            <span style="color:#cc7832">final</span> UidRecord uidRec = mActiveUids.valueAt(i);
            uidRec.reset();
        }
    
        mAdjSeq++;
        mNewNumServiceProcs = <span style="color:#6897bb">0</span>;
        mNewNumAServiceProcs = <span style="color:#6897bb">0</span>;
    
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> emptyProcessLimit;
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> cachedProcessLimit;
        <span style="color:#808080">// mProcessLimit默认值等于32,通过开发者选择可设置,或者厂商会自行调整</span>
        <span style="color:#cc7832">if</span> (mProcessLimit <= <span style="color:#6897bb">0</span>) {
            emptyProcessLimit = cachedProcessLimit = <span style="color:#6897bb">0</span>;
        } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (mProcessLimit == <span style="color:#6897bb">1</span>) {
            emptyProcessLimit = <span style="color:#6897bb">1</span>;
            cachedProcessLimit = <span style="color:#6897bb">0</span>;
        } <span style="color:#cc7832">else</span> {
            <span style="color:#808080">//则emptyProcessLimit = 16, cachedProcessLimit = 16</span>
            emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
            cachedProcessLimit = mProcessLimit - emptyProcessLimit;
        }
    
        <span style="color:#808080">//经过计算得 numSlots =3</span>
        <span style="color:#cc7832">int</span> numSlots = (ProcessList.CACHED_APP_MAX_ADJ
                - ProcessList.CACHED_APP_MIN_ADJ + <span style="color:#6897bb">1</span>) / <span style="color:#6897bb">2</span>;
        <span style="color:#cc7832">int</span> numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
    
        <span style="color:#808080">//确保空进程个数不大于cached进程数</span>
        <span style="color:#cc7832">if</span> (numEmptyProcs > cachedProcessLimit) {
            numEmptyProcs = cachedProcessLimit;
        }
        <span style="color:#cc7832">int</span> emptyFactor = numEmptyProcs/numSlots;
        <span style="color:#cc7832">if</span> (emptyFactor < <span style="color:#6897bb">1</span>) emptyFactor = <span style="color:#6897bb">1</span>;
        <span style="color:#cc7832">int</span> cachedFactor = (mNumCachedHiddenProcs > <span style="color:#6897bb">0</span> ? mNumCachedHiddenProcs : <span style="color:#6897bb">1</span>)/numSlots;
        <span style="color:#cc7832">if</span> (cachedFactor < <span style="color:#6897bb">1</span>) cachedFactor = <span style="color:#6897bb">1</span>;
        <span style="color:#cc7832">int</span> stepCached = <span style="color:#6897bb">0</span>;
        <span style="color:#cc7832">int</span> stepEmpty = <span style="color:#6897bb">0</span>;
        <span style="color:#cc7832">int</span> numCached = <span style="color:#6897bb">0</span>;
        <span style="color:#cc7832">int</span> numEmpty = <span style="color:#6897bb">0</span>;
        <span style="color:#cc7832">int</span> numTrimming = <span style="color:#6897bb">0</span>;
    
        mNumNonCachedProcs = <span style="color:#6897bb">0</span>;
        mNumCachedHiddenProcs = <span style="color:#6897bb">0</span>;
    
        <span style="color:#808080">//更新所有进程状态(基于当前状态)</span>
        <span style="color:#cc7832">int</span> curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
        <span style="color:#cc7832">int</span> nextCachedAdj = curCachedAdj+<span style="color:#6897bb">1</span>;
        <span style="color:#cc7832">int</span> curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
        <span style="color:#cc7832">int</span> nextEmptyAdj = curEmptyAdj+<span style="color:#6897bb">2</span>;
        ProcessRecord selectedAppRecord = <span style="color:#cc7832">null</span>;
        <span style="color:#cc7832">long</span> serviceLastActivity = <span style="color:#6897bb">0</span>;
        <span style="color:#cc7832">int</span> numBServices = <span style="color:#6897bb">0</span>;
        <span style="color:#cc7832">for</span> (<span style="color:#cc7832">int</span> i=N-<span style="color:#6897bb">1</span>; i>=<span style="color:#6897bb">0</span>; i--) {
            ProcessRecord app = mLruProcesses.get(i);
            <span style="color:#cc7832">if</span> (mEnableBServicePropagation && app.serviceb
                    && (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
                numBServices++;
                <span style="color:#cc7832">for</span> (<span style="color:#cc7832">int</span> s = app.services.size() - <span style="color:#6897bb">1</span>; s >= <span style="color:#6897bb">0</span>; s--) {
                    ServiceRecord sr = app.services.valueAt(s);
                    <span style="color:#808080">//上次活跃时间距离现在小于5s,则不会迁移到BService</span>
                    <span style="color:#cc7832">if</span> (SystemClock.uptimeMillis() - sr.lastActivity
                            < mMinBServiceAgingTime) {
                        <span style="color:#cc7832">continue</span>;
                    }
                    <span style="color:#cc7832">if</span> (serviceLastActivity == <span style="color:#6897bb">0</span>) {
                        serviceLastActivity = sr.lastActivity;
                        selectedAppRecord = app;
                    <span style="color:#808080">//记录service上次活动时间最长的那个app</span>
                    } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (sr.lastActivity < serviceLastActivity) {
                        serviceLastActivity = sr.lastActivity;
                        selectedAppRecord = app;
                    }
                }
            }
    
            <span style="color:#cc7832">if</span> (!app.killedByAm && app.thread != <span style="color:#cc7832">null</span>) {
                app.procStateChanged = <span style="color:#cc7832">false</span>;
                <span style="color:#808080">//计算app的adj值【见小节4】</span>
                computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, <span style="color:#cc7832">true</span>, now);
    
                <span style="color:#808080">//当进程未分配adj的情况下,更新adj(cached和empty算法是相同的)</span>
                <span style="color:#cc7832">if</span> (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
                    <span style="color:#cc7832">switch</span> (app.curProcState) {
                        <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                        <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                            <span style="color:#808080">//当进程procState=14或15,则设置adj=9;</span>
                            app.curRawAdj = curCachedAdj;
                            app.curAdj = app.modifyRawOomAdj(curCachedAdj);
                            <span style="color:#808080">//当前cacheadj不等于下一次cachedadj时</span>
                            <span style="color:#cc7832">if</span> (curCachedAdj != nextCachedAdj) {
                                stepCached++;
                                <span style="color:#808080">//当stepCached大于cachedFactor,则将nextCachedAdj赋值给curCachedAdj,</span>
                                <span style="color:#808080">// 并且nextCachedAdj加2,nextCachedAdj最大等于15;</span>
                                <span style="color:#cc7832">if</span> (stepCached >= cachedFactor) {
                                    stepCached = <span style="color:#6897bb">0</span>;
                                    curCachedAdj = nextCachedAdj;
                                    nextCachedAdj += <span style="color:#6897bb">2</span>;
                                    <span style="color:#cc7832">if</span> (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                        nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                    }
                                }
                            }
                            <span style="color:#cc7832">break</span>;
                        <span style="color:#cc7832">default</span>:
                            app.curRawAdj = curEmptyAdj;
                            app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                            <span style="color:#808080">//更新curCachedAdj值</span>
                            <span style="color:#cc7832">if</span> (curEmptyAdj != nextEmptyAdj) {
                                stepEmpty++;
                                <span style="color:#808080">//当stepEmpty大于emptyFactor,则将nextEmptyAdj赋值给curEmptyAdj,</span>
                                <span style="color:#808080">//并且nextEmptyAdj加2,nextEmptyAdj最大等于15;</span>
                                <span style="color:#cc7832">if</span> (stepEmpty >= emptyFactor) {
                                    stepEmpty = <span style="color:#6897bb">0</span>;
                                    curEmptyAdj = nextEmptyAdj;
                                    nextEmptyAdj += <span style="color:#6897bb">2</span>;
                                    <span style="color:#cc7832">if</span> (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                        nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                    }
                                }
                            }
                            <span style="color:#cc7832">break</span>;
                    }
                }
    
                <span style="color:#808080">//【见小节2.5】</span>
                applyOomAdjLocked(app, <span style="color:#cc7832">true</span>, now, nowElapsed);
    
                <span style="color:#808080">//根据当前进程procState状态来决策</span>
                <span style="color:#cc7832">switch</span> (app.curProcState) {
                    <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                    <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        mNumCachedHiddenProcs++;
                        numCached++;
                        <span style="color:#808080">// 当cached进程超过上限(cachedProcessLimit),则杀掉该进程</span>
                        <span style="color:#cc7832">if</span> (numCached > cachedProcessLimit) {
                            app.kill(<span style="color:#6a8759">"cached #"</span> + numCached, <span style="color:#cc7832">true</span>);
                        }
                        <span style="color:#cc7832">break</span>;
                    <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                        <span style="color:#808080">// 当空进程超过上限(TRIM_EMPTY_APPS),且空闲时间超过30分钟,则杀掉该进程</span>
                        <span style="color:#cc7832">if</span> (numEmpty > ProcessList.TRIM_EMPTY_APPS
                                && app.lastActivityTime < oldTime) {
                            app.kill(<span style="color:#6a8759">"empty for "</span>
                                    + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
                                    / <span style="color:#6897bb">1000</span>) + <span style="color:#6a8759">"s"</span>, <span style="color:#cc7832">true</span>);
                        } <span style="color:#cc7832">else</span> {
                            <span style="color:#808080">// 当空进程超过上限(emptyProcessLimit),则杀掉该进程</span>
                            numEmpty++;
                            <span style="color:#cc7832">if</span> (numEmpty > emptyProcessLimit) {
                                <span style="color:#cc7832">if</span> (!CT_PROTECTED_PROCESS.equals(app.processName))
                                    app.kill(<span style="color:#6a8759">"empty #"</span> + numEmpty, <span style="color:#cc7832">true</span>);
                            }
                        }
                        <span style="color:#cc7832">break</span>;
                    <span style="color:#cc7832">default</span>:
                        mNumNonCachedProcs++;
                        <span style="color:#cc7832">break</span>;
                }
    
                <span style="color:#cc7832">if</span> (app.isolated && app.services.size() <= <span style="color:#6897bb">0</span>) {
                    <span style="color:#808080">//没有services运行的孤立进程,则直接杀掉</span>
                    app.kill(<span style="color:#6a8759">"isolated not needed"</span>, <span style="color:#cc7832">true</span>);
                } <span style="color:#cc7832">else</span> {
                    <span style="color:#cc7832">final</span> UidRecord uidRec = app.uidRecord;
                    <span style="color:#cc7832">if</span> (uidRec != <span style="color:#cc7832">null</span> && uidRec.curProcState > app.curProcState) {
                        uidRec.curProcState = app.curProcState;
                    }
                }
    
                <span style="color:#cc7832">if</span> (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                        && !app.killedByAm) {
                    numTrimming++;
                }
            }
        }
    
        <span style="color:#808080">//当BServices个数超过上限(mBServiceAppThreshold),则</span>
        <span style="color:#cc7832">if</span> ((numBServices > mBServiceAppThreshold) && (<span style="color:#cc7832">true</span> == mAllowLowerMemLevel)
                && (selectedAppRecord != <span style="color:#cc7832">null</span>)) {
            ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
                    ProcessList.CACHED_APP_MAX_ADJ);
            selectedAppRecord.setAdj = selectedAppRecord.curAdj;
        }
        mNumServiceProcs = mNewNumServiceProcs;
    
        <span style="color:#808080">//根据CachedAndEmpty个数来调整内存因子memFactor</span>
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> numCachedAndEmpty = numCached + numEmpty;
        <span style="color:#cc7832">int</span> memFactor;
        <span style="color:#cc7832">if</span> (numCached <= ProcessList.TRIM_CACHED_APPS
                && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
            <span style="color:#cc7832">if</span> (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
                memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
            } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
                memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
            } <span style="color:#cc7832">else</span> {
                memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
            }
        } <span style="color:#cc7832">else</span> {
            memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
        }
    
        <span style="color:#cc7832">if</span> (memFactor > mLastMemoryLevel) {
            <span style="color:#cc7832">if</span> (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
                memFactor = mLastMemoryLevel;
            }
        }
        mLastMemoryLevel = memFactor;
        mLastNumProcesses = mLruProcesses.size();
        <span style="color:#cc7832">boolean</span> allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
        <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> trackerMemFactor = mProcessStats.getMemFactorLocked();
        <span style="color:#808080">//当内存因子不是普通0级别的情况下</span>
        <span style="color:#cc7832">if</span> (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
            <span style="color:#cc7832">if</span> (mLowRamStartTime == <span style="color:#6897bb">0</span>) {
                mLowRamStartTime = now;
            }
            <span style="color:#cc7832">int</span> step = <span style="color:#6897bb">0</span>;
            <span style="color:#cc7832">int</span> fgTrimLevel;
            <span style="color:#cc7832">switch</span> (memFactor) {
                <span style="color:#cc7832">case</span> ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
                    <span style="color:#cc7832">break</span>;
                <span style="color:#cc7832">case</span> ProcessStats.ADJ_MEM_FACTOR_LOW:
                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
                    <span style="color:#cc7832">break</span>;
                <span style="color:#cc7832">default</span>:
                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
                    <span style="color:#cc7832">break</span>;
            }
            <span style="color:#cc7832">int</span> factor = numTrimming/<span style="color:#6897bb">3</span>;
            <span style="color:#cc7832">int</span> minFactor = <span style="color:#6897bb">2</span>;
            <span style="color:#cc7832">if</span> (mHomeProcess != <span style="color:#cc7832">null</span>) minFactor++;
            <span style="color:#cc7832">if</span> (mPreviousProcess != <span style="color:#cc7832">null</span>) minFactor++;
            <span style="color:#cc7832">if</span> (factor < minFactor) factor = minFactor;
    
            <span style="color:#808080">//TRIM_MEMORY_COMPLETE:该进程处于LRU队列的尾部,当进程不足则会杀掉该进程</span>
            <span style="color:#cc7832">int</span> curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
            <span style="color:#cc7832">for</span> (<span style="color:#cc7832">int</span> i=N-<span style="color:#6897bb">1</span>; i>=<span style="color:#6897bb">0</span>; i--) {
                ProcessRecord app = mLruProcesses.get(i);
                <span style="color:#cc7832">if</span> (allChanged || app.procStateChanged) {
                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
                    app.procStateChanged = <span style="color:#cc7832">false</span>;
                }
                <span style="color:#808080">//当curProcState > 12且没有被am杀掉的情况;</span>
                <span style="color:#cc7832">if</span> (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                        && !app.killedByAm) {
                    <span style="color:#cc7832">if</span> (app.trimMemoryLevel < curLevel && app.thread != <span style="color:#cc7832">null</span>) {
                        <span style="color:#808080">//调度app执行trim memory的操作</span>
                        app.thread.scheduleTrimMemory(curLevel);
                    }
                    app.trimMemoryLevel = curLevel;
                    step++;
                    <span style="color:#cc7832">if</span> (step >= factor) {
                        step = <span style="color:#6897bb">0</span>;
                        <span style="color:#cc7832">switch</span> (curLevel) {
                            <span style="color:#cc7832">case</span> ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                                curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
                                <span style="color:#cc7832">break</span>;
                            <span style="color:#cc7832">case</span> ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                                curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
                                <span style="color:#cc7832">break</span>;
                        }
                    }
                } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                    <span style="color:#cc7832">if</span> (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
                            && app.thread != <span style="color:#cc7832">null</span>) {
                        app.thread.scheduleTrimMemory(
                                ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                    }
                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
                } <span style="color:#cc7832">else</span> {
                    <span style="color:#cc7832">if</span> ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                            || app.systemNoUi) && app.pendingUiClean) {
                        <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                        <span style="color:#cc7832">if</span> (app.trimMemoryLevel < level && app.thread != <span style="color:#cc7832">null</span>) {
                            app.thread.scheduleTrimMemory(level);
                        }
                        app.pendingUiClean = <span style="color:#cc7832">false</span>;
                    }
                    <span style="color:#cc7832">if</span> (app.trimMemoryLevel < fgTrimLevel && app.thread != <span style="color:#cc7832">null</span>) {
                        app.thread.scheduleTrimMemory(fgTrimLevel);
                    }
                    app.trimMemoryLevel = fgTrimLevel;
                }
            }
        } <span style="color:#cc7832">else</span> {
            <span style="color:#cc7832">if</span> (mLowRamStartTime != <span style="color:#6897bb">0</span>) {
                mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
                mLowRamStartTime = <span style="color:#6897bb">0</span>;
            }
            <span style="color:#cc7832">for</span> (<span style="color:#cc7832">int</span> i=N-<span style="color:#6897bb">1</span>; i>=<span style="color:#6897bb">0</span>; i--) {
                ProcessRecord app = mLruProcesses.get(i);
                <span style="color:#cc7832">if</span> (allChanged || app.procStateChanged) {
                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
                    app.procStateChanged = <span style="color:#cc7832">false</span>;
                }
                <span style="color:#cc7832">if</span> ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                        || app.systemNoUi) && app.pendingUiClean) {
                    <span style="color:#cc7832">if</span> (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
                            && app.thread != <span style="color:#cc7832">null</span>) {
                        app.thread.scheduleTrimMemory(
                                ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
                    }
                    app.pendingUiClean = <span style="color:#cc7832">false</span>;
                }
                app.trimMemoryLevel = <span style="color:#6897bb">0</span>;
            }
        }
    
        <span style="color:#808080">//是否finish activity</span>
        <span style="color:#cc7832">if</span> (mAlwaysFinishActivities) {
            mStackSupervisor.scheduleDestroyAllActivities(<span style="color:#cc7832">null</span>, <span style="color:#6a8759">"always-finish"</span>);
        }
    
        <span style="color:#cc7832">if</span> (allChanged) {
            requestPssAllProcsLocked(now, <span style="color:#cc7832">false</span>, mProcessStats.isMemFactorLowered());
        }
    
        <span style="color:#808080">//更新 uid的改变</span>
        <span style="color:#cc7832">for</span> (<span style="color:#cc7832">int</span> i=mActiveUids.size()-<span style="color:#6897bb">1</span>; i>=<span style="color:#6897bb">0</span>; i--) {
            <span style="color:#cc7832">final</span> UidRecord uidRec = mActiveUids.valueAt(i);
            <span style="color:#cc7832">if</span> (uidRec.setProcState != uidRec.curProcState) {
                uidRec.setProcState = uidRec.curProcState;
                enqueueUidChangeLocked(uidRec, <span style="color:#cc7832">false</span>);
            }
        }
        ...
    }
    </code></span></span>

    3.5小节

    updateOomAdjLocked过程比较复杂,主要分为更新adj(满足条件则杀进程)和根据memFactor来调度执行TrimMemory操作;

    第一部分:更新adj(满足条件则杀进程)

    • 遍历mLruProcesses进度
      • 当进展未分配adj的情况
        • 当进程procState = 14或15,则设置adj=curCachedAdj(初始化=9);
          • 当curCachedAdj!= nextCachedAdj,并且stepCached大于cachedFactor时则curCachedAdj = nextCachedAdj,(nextCachedAdj加2,nextCachedAdj上限为15);
        • 否则,则设置adj=curEmptyAdj(初始化=9);
          • 当curEmptyAdj!= nextEmptyAdj,并且stepEmpty大于EmptyFactor时则curEmptyAdj = nextEmptyAdj,(nextEmptyAdj加2,nextEmptyAdj上限为15);
      • 根据当前进程procState状态来决定:
        • 当curProcState = 14或15,且cached进度超过上限(cachedProcessLimit = 16),则杀掉该进程
        • 当curProcState = 16的预定下:
          • 当空进程超过上限(TRIM_EMPTY_APPS = 8),且间隔时间超过30分钟,则杀掉该进程
          • 否则,当空进程超过上限(emptyProcessLimit = 16),则杀掉该进程
      • 没有services运行的孤立进展,则杀掉该进程;

    第二部分:根据memFactor来调度执行TrimMemory操作;

    • 根据CachedAndEmpty个数来调整内存因子memFactor(值大小,级别升高):
      • 当CachedAndEmpty <3,则memFactor = 3;
      • 当CachedAndEmpty <5,则memFactor = 2;
      • 当CachedAndEmpty> = 5,且numCached <= 5,numEmpty <= 8,则memFactor = 1;
      • 当numCached> 5或numEmpty> 8,则memFactor = 0;
    • 当内存因子不是普通0等级的情况下,根据memFactor来调整前台trim等级(fgTrimLevel):
      • 当memFactor = 3,则fgTrimLevel = TRIM_MEMORY_RUNNING_CRITICAL;
      • 当memFactor = 2,则fgTrimLevel = TRIM_MEMORY_RUNNING_LOW;
      • 否则(实际上就是memFactor = 1),则fgTrimLevel = TRIM_MEMORY_RUNNING_MODERATE

      • 再遍历mLruProcesses物理进展:
        • 当curProcState> 12且没有被am杀掉,则执行TrimMemory操作;
        • 否则,当curProcState = 9且trimMemoryLevel <TRIM_MEMORY_BACKGROUND,则执行TrimMemory操作;
        • 否则,当curProcState> 7,且待定UiClean = true时
          • 当trimMemoryLevel <TRIM_MEMORY_UI_HIDDEN,则执行TrimMemory操作;
          • 当trimMemoryLevel <fgTrimLevel,则执行TrimMemory操作;
    • 当内存因子等于0的情况下,遍历mLruProcesses进程:
      • 当curProcState> = 7,且pendingUiClean = true时,
        • 当trimMemoryLevel <TRIM_MEMORY_UI_HIDDEN,则执行TrimMemory操作;

    四。computeOomAdjLocked

    <span style="color:#404040"><span style="color:#333333"><code><span style="color:#cc7832">private</span> <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> <span style="color:#ffc66d">computeOomAdjLocked</span>(ProcessRecord app, <span style="color:#cc7832">int</span> cachedAdj, ProcessRecord TOP_APP, <span style="color:#cc7832">boolean</span> doingAll, <span style="color:#cc7832">long</span> now);</code></span></span>

    该方法比较长,下面分几个几个部分来展开说明,每一部分后主要功能便是设置adj和procState(进程状态):(adj和procState的取值原则具有优先级高为主)

    1.空进程情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (mAdjSeq == app.adjSeq) {
         <span style="color:#cc7832">return</span> app.curRawAdj; <span style="color:#808080">//已经调整完成</span>
     }
    
     <span style="color:#808080">// 当进程对象为空时,则设置curProcState=16, curAdj=curRawAdj=15</span>
     <span style="color:#cc7832">if</span> (app.thread == <span style="color:#cc7832">null</span>) {
         app.adjSeq = mAdjSeq;
         app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
         app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
         <span style="color:#cc7832">return</span> (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
     }
    </code></span></span>

    2. maxAdj <= 0情况

    <span style="color:#404040"><span style="color:#333333"><code><span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> activitiesSize = app.activities.size();
     <span style="color:#cc7832">if</span> (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
         app.adjType = <span style="color:#6a8759">"fixed"</span>;
         app.adjSeq = mAdjSeq;
         app.curRawAdj = app.maxAdj;
         app.foregroundActivities = <span style="color:#cc7832">false</span>;
         app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
         app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
    
         app.systemNoUi = <span style="color:#cc7832">true</span>;
         <span style="color:#808080">//顶部的activity就是当前app,则代表正处于展现UI</span>
         <span style="color:#cc7832">if</span> (app == TOP_APP) {
             app.systemNoUi = <span style="color:#cc7832">false</span>;
         <span style="color:#808080">//进程中的activity个数大于0时</span>
         } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (activitiesSize > <span style="color:#6897bb">0</span>) {
             <span style="color:#cc7832">for</span> (<span style="color:#cc7832">int</span> j = <span style="color:#6897bb">0</span>; j < activitiesSize; j++) {
                 <span style="color:#cc7832">final</span> ActivityRecord r = app.activities.get(j);
                 <span style="color:#cc7832">if</span> (r.visible) {
                     app.systemNoUi = <span style="color:#cc7832">false</span>;
                 }
             }
         }
         <span style="color:#cc7832">if</span> (!app.systemNoUi) {
             app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
         }
         <span style="color:#cc7832">return</span> (app.curAdj=app.maxAdj);
     }
    </code></span></span>

    当maxAdj <= 0的情况,也就意味这暂时app将其adj调整到后续前台app的优先级别,这样场景下执行后将直接返回:

    • curProcState = PROCESS_STATE_PERSISTENT或PROCESS_STATE_PERSISTENT_UI(存在可见的活动)
    • curAdj = app.maxAdj(curAdj <= 0)

    3.前台的情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (app == TOP_APP) {
         adj = ProcessList.FOREGROUND_APP_ADJ;
         schedGroup = Process.THREAD_GROUP_DEFAULT;
         app.adjType = <span style="color:#6a8759">"top-activity"</span>;
         foregroundActivities = <span style="color:#cc7832">true</span>;
         procState = PROCESS_STATE_TOP;
         <span style="color:#cc7832">if</span>(app == mHomeProcess) {
             mHomeKilled = <span style="color:#cc7832">false</span>;
             mHomeProcessName = mHomeProcess.processName;
         }
     } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (app.instrumentationClass != <span style="color:#cc7832">null</span>) {
         adj = ProcessList.FOREGROUND_APP_ADJ;
         schedGroup = Process.THREAD_GROUP_DEFAULT;
         app.adjType = <span style="color:#6a8759">"instrumentation"</span>;
         procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
     } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> ((queue = isReceivingBroadcast(app)) != <span style="color:#cc7832">null</span>) {
         adj = ProcessList.FOREGROUND_APP_ADJ;
         schedGroup = (queue == mFgBroadcastQueue)
                 ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
         app.adjType = <span style="color:#6a8759">"broadcast"</span>;
         procState = ActivityManager.PROCESS_STATE_RECEIVER;
     } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (app.executingServices.size() > <span style="color:#6897bb">0</span>) {
         adj = ProcessList.FOREGROUND_APP_ADJ;
         schedGroup = app.execServicesFg ?
                 Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
         app.adjType = <span style="color:#6a8759">"exec-service"</span>;
         procState = ActivityManager.PROCESS_STATE_SERVICE;
     } <span style="color:#cc7832">else</span> {
         <span style="color:#808080">//top app; isReceivingBroadcast;executingServices;</span>
         <span style="color:#808080">// 除此之外则为PROCESS_STATE_CACHED_EMPTY</span>
         schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
         adj = cachedAdj;
         procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
         app.cached = <span style="color:#cc7832">true</span>;
         app.<span style="color:#cc7832">empty</span> = <span style="color:#cc7832">true</span>;
         app.adjType = <span style="color:#6a8759">"cch-empty"</span>;
    
         <span style="color:#cc7832">if</span> (mHomeKilled && app.processName.equals(mHomeProcessName)) {
             adj = ProcessList.PERSISTENT_PROC_ADJ;
             schedGroup = Process.THREAD_GROUP_DEFAULT;
             app.cached = <span style="color:#cc7832">false</span>;
             app.<span style="color:#cc7832">empty</span> = <span style="color:#cc7832">false</span>;
             app.adjType = <span style="color:#6a8759">"top-activity"</span>;
         }
     }
    </code></span></span>
    案件调整procState
    当app是当前展示的appadj = 0procState = 2
    当instrumentation不为空时adj = 0procState = 4
    当进展存在正在接收的broadcastrecevieradj = 0procState = 11
    当进展存在正在执行的服务adj = 0procState = 10
    以上条件都不符合adj = cachedAdj(> = 0)procState = 16

    4.非前台活动的情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (!foregroundActivities && activitiesSize > <span style="color:#6897bb">0</span>) {
         <span style="color:#cc7832">for</span> (int j = <span style="color:#6897bb">0</span>; j < activitiesSize; j++) {
             <span style="color:#cc7832">final</span> ActivityRecord r = app.activities.get(j);
             <span style="color:#cc7832">if</span> (r.app != app) {
                 <span style="color:#cc7832">continue</span>;
             }
             当activity可见, 则adj=<span style="color:#6897bb">1</span>,procState=<span style="color:#6897bb">2</span>
             <span style="color:#cc7832">if</span> (r.visible) {
                 <span style="color:#cc7832">if</span> (adj > ProcessList.VISIBLE_APP_ADJ) {
                     adj = ProcessList.VISIBLE_APP_ADJ;
                     app.adjType = <span style="color:#6a8759">"visible"</span>;
                 }
                 <span style="color:#cc7832">if</span> (procState > PROCESS_STATE_TOP) {
                     procState = PROCESS_STATE_TOP;
                 }
                 schedGroup = Process.THREAD_GROUP_DEFAULT;
                 app.cached = <span style="color:#cc7832">false</span>;
                 app.<span style="color:#cc7832">empty</span> = <span style="color:#cc7832">false</span>;
                 foregroundActivities = <span style="color:#cc7832">true</span>;
                 <span style="color:#cc7832">break</span>;
             当activity正在暂停或者已经暂停, 则adj=<span style="color:#6897bb">2</span>,procState=<span style="color:#6897bb">2</span>
             } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
                 <span style="color:#cc7832">if</span> (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                     adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                     app.adjType = <span style="color:#6a8759">"pausing"</span>;
                 }
                 <span style="color:#cc7832">if</span> (procState > PROCESS_STATE_TOP) {
                     procState = PROCESS_STATE_TOP;
                 }
                 schedGroup = Process.THREAD_GROUP_DEFAULT;
                 app.cached = <span style="color:#cc7832">false</span>;
                 app.<span style="color:#cc7832">empty</span> = <span style="color:#cc7832">false</span>;
                 foregroundActivities = <span style="color:#cc7832">true</span>;
             当activity正在停止, 则adj=<span style="color:#6897bb">2</span>,procState=<span style="color:#6897bb">13</span>(activity尚未finish)
             } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (r.state == ActivityState.STOPPING) {
                 <span style="color:#cc7832">if</span> (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                     adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                     app.adjType = <span style="color:#6a8759">"stopping"</span>;
                 }
    
                 <span style="color:#cc7832">if</span> (!r.finishing) {
                     <span style="color:#cc7832">if</span> (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                         procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
                     }
                 }
                 app.cached = <span style="color:#cc7832">false</span>;
                 app.<span style="color:#cc7832">empty</span> = <span style="color:#cc7832">false</span>;
                 foregroundActivities = <span style="color:#cc7832">true</span>;
             否则procState=<span style="color:#6897bb">14</span>
             } <span style="color:#cc7832">else</span> {
                 <span style="color:#cc7832">if</span> (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                     procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
                     app.adjType = <span style="color:#6a8759">"cch-act"</span>;
                 }
             }
         }
     }
    </code></span></span>

    对于进展中的活动处于非前台情况

    • 当活动可见,则adj = 1,procState = 2;
    • 当activity正在暂停或已经暂停,则adj = 2,procState = 2;
    • 当activity正在停止时,则adj = 2,procState = 13(且activity尚未完成);
    • 以上都不满足,否则procState = 14

    5. adj> 2的情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
         当存在前台service时,则adj=2, procState=4;
         <span style="color:#cc7832">if</span> (app.foregroundServices) {
             adj = ProcessList.PERCEPTIBLE_APP_ADJ;
             procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
             app.cached = <span style="color:#6897bb">false</span>;
             app.adjType = <span style="color:#6a8759">"fg-service"</span>;
             schedGroup = Process.THREAD_GROUP_DEFAULT;
         当强制前台时,则adj=2, procState=6;
         } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (app.forcingToForeground != null) {
             adj = ProcessList.PERCEPTIBLE_APP_ADJ;
             procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
             app.cached = <span style="color:#6897bb">false</span>;
             app.adjType = <span style="color:#6a8759">"force-fg"</span>;
             app.adjSource = app.forcingToForeground;
             schedGroup = Process.THREAD_GROUP_DEFAULT;
         }
     }
    </code></span></span>

    当adj> 2的情况的必然下:

    • 当存在前台服务时,则adj = 2,procState = 4;
    • 当强制前台时,则adj = 2,procState = 6;

    6. HeavyWeightProces情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (app == mHeavyWeightProcess) {
         <span style="color:#cc7832">if</span> (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
             adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
             schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.cached = <span style="color:#6897bb">false</span>;
             app.adjType = <span style="color:#6a8759">"heavy"</span>;
         }
         <span style="color:#cc7832">if</span> (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
             procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
         }
     }
    </code></span></span>

    当进程为HeavyWeightProcess,则adj = 4,procState = 9;

    7. HomeProcess情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (app == mHomeProcess) {
         <span style="color:#cc7832">if</span> (adj > ProcessList.HOME_APP_ADJ) {
             adj = ProcessList.HOME_APP_ADJ;
             schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.cached = <span style="color:#6897bb">false</span>;
             app.adjType = <span style="color:#6a8759">"home"</span>;
         }
         <span style="color:#cc7832">if</span> (procState > ActivityManager.PROCESS_STATE_HOME) {
             procState = ActivityManager.PROCESS_STATE_HOME;
         }
     }
    </code></span></span>

    当进展为HomeProcess情况,则adj = 6,procState = 12;

    8. PreviousProcess情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (app == mPreviousProcess && app.activities.size() > 0) {
         <span style="color:#cc7832">if</span> (adj > ProcessList.PREVIOUS_APP_ADJ) {
             adj = ProcessList.PREVIOUS_APP_ADJ;
             schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.cached = <span style="color:#6897bb">false</span>;
             app.adjType = <span style="color:#6a8759">"previous"</span>;
         }
         <span style="color:#cc7832">if</span> (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
             procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
         }
     }
    </code></span></span>

    当进程为PreviousProcess情况,则adj = 7,procState = 13;

    9.备份进程情况

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#cc7832">if</span> (mBackupTarget != <span style="color:#cc7832">null</span> && app == mBackupTarget.app) {
         <span style="color:#cc7832">if</span> (adj > ProcessList.BACKUP_APP_ADJ) {
             adj = ProcessList.BACKUP_APP_ADJ;
             <span style="color:#cc7832">if</span> (procState > ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                 procState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
             }
             app.adjType = <span style="color:#6a8759">"backup"</span>;
             app.cached = <span style="color:#cc7832">false</span>;
         }
         <span style="color:#cc7832">if</span> (procState > ActivityManager.PROCESS_STATE_BACKUP) {
             procState = ActivityManager.PROCESS_STATE_BACKUP;
         }
     }
    </code></span></span>

    对于备份进程的情况,则adj = 3,procState = 7或8

    10.服务情况

    //是否显示在最顶部
    boolean mayBeTop = false;
    for (int is = app.services.size()-1;
           is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                   || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                   || procState > ActivityManager.PROCESS_STATE_TOP);
           is--) {
       //当adj>0 或 schedGroup为后台线程组 或procState>2时执行
       ServiceRecord s = app.services.valueAt(is);
       if (s.startRequested) {
           app.hasStartedServices = true;
           //当service已启动,则procState<=10;
           if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
               procState = ActivityManager.PROCESS_STATE_SERVICE;
           }
           if (app.hasShownUi && app != mHomeProcess) {
               if (adj > ProcessList.SERVICE_ADJ) {
                   app.adjType = "cch-started-ui-services";
               }
           } else {
               if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) {
                   //当service在30分钟内活动过,则adj=5;
                   if (adj > ProcessList.SERVICE_ADJ) {
                       adj = ProcessList.SERVICE_ADJ;
                       app.adjType = "started-services";
                       app.cached = false;
                   }
               }
               if (adj > ProcessList.SERVICE_ADJ) {
                   app.adjType = "cch-started-services";
               }
           }
       }
    
       for (int conni = s.connections.size()-1;
               conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                       || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                       || procState > ActivityManager.PROCESS_STATE_TOP);
               conni--) {
           // 获取service所绑定的connections
           ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
           for (int i = 0;
                   i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
                           || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                           || procState > ActivityManager.PROCESS_STATE_TOP);
                   i++) {
               ConnectionRecord cr = clist.get(i);
               //当client与当前app同一个进程,则continue;
               if (cr.binding.client == app) {
                   continue;
               }
               if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                   ProcessRecord client = cr.binding.client;
                   //计算connections所对应的client进程的adj
                   int clientAdj = computeOomAdjLocked(client, cachedAdj,
                           TOP_APP, doingAll, now);
                   int clientProcState = client.curProcState;
    
                   //当client进程的ProcState >=cache,则设置为空进程
                   if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                       clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                   }
                   String adjType = null;
                   if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                       //当进程存在显示的ui,则将当前进程的adj和ProcState值赋予给client进程
                       if (app.hasShownUi && app != mHomeProcess) {
                           if (adj > clientAdj) {
                               adjType = "cch-bound-ui-services";
                           }
                           app.cached = false;
                           clientAdj = adj;
                           clientProcState = procState;
                       } else {
                           //当不存在显示的ui,且service上次活动时间距离现在超过30分钟,则只将当前进程的adj值赋予给client进程
                           if (now >= (s.lastActivity
                                   + ActiveServices.MAX_SERVICE_INACTIVITY)) {
                               if (adj > clientAdj) {
                                   adjType = "cch-bound-services";
                               }
                               clientAdj = adj;
                           }
                       }
                   }
                   //当前进程adj > client进程adj的情况
                   if (adj > clientAdj) {
                       if (app.hasShownUi && app != mHomeProcess
                               && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                           adjType = "cch-bound-ui-services";
                       } else {
                           //当service进程比较重要时,设置adj >= -11
                           if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                   |Context.BIND_IMPORTANT)) != 0) {
                               adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
                                       ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;
                           //当client进程adj<2,且当前进程adj>2时,设置adj=2;
                           } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                   && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                   && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                               adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                           //当client进程adj>1时,则设置adj = clientAdj
                           } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
                               adj = clientAdj;
                           } else {
                               //否则,设置adj <= 1
                               if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                   adj = ProcessList.VISIBLE_APP_ADJ;
                               }
                           }
                           //当client进程不是cache进程,则当前进程也设置为非cache进程
                           if (!client.cached) {
                               app.cached = false;
                           }
                           adjType = "service";
                       }
                   }
    
                   //当绑定的是前台进程的情况
                   if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                       if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
                           schedGroup = Process.THREAD_GROUP_DEFAULT;
                       }
                       if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
                           //当client进程状态为前台时,则设置mayBeTop=true,并设置client进程procState=16
                           if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
                               mayBeTop = true;
                               clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                           //当client进程状态 < 2的前提下:若绑定前台service,则clientProcState=3;否则clientProcState=6
                           } else {
                               if ((cr.flags&Context.BIND_FOREGROUND_SERVICE) != 0) {
                                   clientProcState =
                                           ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                               } else if (mWakefulness
                                               == PowerManagerInternal.WAKEFULNESS_AWAKE &&
                                       (cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
                                               != 0) {
                                   clientProcState =
                                           ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                               } else {
                                   clientProcState =
                                           ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
                               }
                           }
                       }
                   //当connections并没有绑定前台service时,则clientProcState >= 7
                   } else {
                       if (clientProcState <
                               ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                           clientProcState =
                                   ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
                       }
                   }
                   //保证当前进程procState不会必client进程的procState大
                   if (procState > clientProcState) {
                       procState = clientProcState;
                   }
                   if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                           && (cr.flags&Context.BIND_SHOWING_UI) != 0) {
                       app.pendingUiClean = true;
                   }
                   if (adjType != null) {
                       app.adjType = adjType;
                       app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                               .REASON_SERVICE_IN_USE;
                       app.adjSource = cr.binding.client;
                       app.adjSourceProcState = clientProcState;
                       app.adjTarget = s.name;
                   }
               }
               if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                   app.treatLikeActivity = true;
               }
               final ActivityRecord a = cr.activity;
               if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
                   //当进程adj >0,且activity可见 或者resumed 或 正在暂停,则设置adj = 0
                   if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
                           (a.visible || a.state == ActivityState.RESUMED
                            || a.state == ActivityState.PAUSING)) {
                       adj = ProcessList.FOREGROUND_APP_ADJ;
                       if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                           schedGroup = Process.THREAD_GROUP_DEFAULT;
                       }
                       app.cached = false;
                       app.adjType = "service";
                       app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                               .REASON_SERVICE_IN_USE;
                       app.adjSource = a;
                       app.adjSourceProcState = procState;
                       app.adjTarget = s.name;
                   }
               }
           }
       }
    }
    

    当adj> 0或schedGroup为后台线程组或procState> 2时,双重循环遍历:

    • 当service已启动,则procState <= 10;
      • 当service在30分钟内活动过,则adj = 5,cached = false;
    • 获取服务所绑定的连接
      • 当客户端与当前app同一个进程,则继续;
      • 当客户端进程的ProcState> = cache,则设置为空进程
      • 当进程存在显示的ui,则将当前进程的adj和ProcState值赋予给客户端进程
      • 当不存在显示的ui,且服务上次活动时间距离现在超过30分钟,则只将当前进程的adj值赋予给客户端进程
      • 当前进度adj> client进展adj的情况
        • 当service进展比较重要时,则设置adj> = -11
        • 当clientgressadj <2,且当前进程adj> 2时,则设置adj = 2;
        • 当client进展adj> 1时,则设置adj = clientAdj
        • 否则,设置adj <= 1;
        • 若client进程不是缓存进程,则当前进程也设置为非缓存进程
      • 当绑定的是前台进展的情况
        • 当客户端进程状态为前台时,则设置mayBeTop = true,并设置客户端进程procState = 16
        • 当client进展状态<2的前提下:若绑定前台服务,则clientProcState = 3;否则clientProcState = 6
      • 当connections并没有绑定前台服务时,则clientProcState> = 7
      • 保证当前进程procState不会必是客户端进程的procState大
    • 当进度adj> 0,且活动可见或恢复或正在暂停,则设置adj = 0

    11. ContentProvider情况

    //当adj>0 或 schedGroup为后台线程组 或procState>2时
    for (int provi = app.pubProviders.size()-1;
           provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                   || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                   || procState > ActivityManager.PROCESS_STATE_TOP);
           provi--) {
       ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
       for (int i = cpr.connections.size()-1;
               i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                       || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
                       || procState > ActivityManager.PROCESS_STATE_TOP);
               i--) {
           ContentProviderConnection conn = cpr.connections.get(i);
           ProcessRecord client = conn.client;
           // 当client与当前app同一个进程,则continue;
           if (client == app) {
               continue;
           }
           // 计算client进程的adj
           int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
           int clientProcState = client.curProcState;
           //当client进程procState >=14,则设置成procState =16
           if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
               clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; 【】
           }
           if (adj > clientAdj) {
               if (app.hasShownUi && app != mHomeProcess
                       && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                   app.adjType = "cch-ui-provider";
               } else {
                   //没有ui展示,则保证adj >=0
                   adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                           ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
                   app.adjType = "provider";
               }
               app.cached &= client.cached;
               app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                       .REASON_PROVIDER_IN_USE;
               app.adjSource = client;
               app.adjSourceProcState = clientProcState;
               app.adjTarget = cpr.name;
           }
           if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
               if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
                   mayBeTop = true;
                   //当client进程状态为前台时,则设置mayBeTop=true,并设置client进程procState=16设置为空进程
                   clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
               } else {
                   //当client进程状态 < 2时,则clientProcState=3;
                   clientProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
               }
           }
           //procState 比client进程值更大时,则取client端的状态值。
           if (procState > clientProcState) {
               procState = clientProcState;
           }
           if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
               schedGroup = Process.THREAD_GROUP_DEFAULT;
           }
       }
       //当contentprovider存在外部进程依赖(非framework)时
       if (cpr.hasExternalProcessHandles()) {
           //设置adj =0, procState=6
           if (adj > ProcessList.FOREGROUND_APP_ADJ) {
               adj = ProcessList.FOREGROUND_APP_ADJ;
               schedGroup = Process.THREAD_GROUP_DEFAULT;
               app.cached = false;
               app.adjType = "provider";
               app.adjTarget = cpr.name;
           }
           if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
               procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
           }
       }
    }
    

    当adj> 0或schedGroup为后台线程组或procState> 2时,双重循环遍历:

    • 当客户端与当前app同一个进程,则继续;
    • 当clientprocprocState> = 14,则把clientproc设置成procState = 16
    • 没有ui展示,则保证adj> = 0
    • 当clientproc状态= 2()前台)时,则设置mayBeTop = true,并设置client进程procState = 16(空进程)
    • 当client进展状态<2时,则clientProcState = 3;
    • procState比clientProcState例外时,则取客户端端的状态值。
    • 当contentprovider存在外部进程依赖(nonframework)时,则设置adj = 0,procState = 6

    12.调整adj

    <span style="color:#404040"><span style="color:#333333"><code> <span style="color:#808080">// 当client进程处于top,且procState>2时</span>
     <span style="color:#cc7832">if</span> (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) {
         <span style="color:#cc7832">switch</span> (procState) {
             <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
             <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
             <span style="color:#cc7832">case</span> ActivityManager.PROCESS_STATE_SERVICE:
                 <span style="color:#808080">//对于procState=6,7,10时,则设置成3</span>
                 procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
                 <span style="color:#cc7832">break</span>;
             <span style="color:#cc7832">default</span>:
                 <span style="color:#808080">//其他情况,直接设置成2</span>
                 procState = ActivityManager.PROCESS_STATE_TOP;
                 <span style="color:#cc7832">break</span>;
         }
     }
    
     <span style="color:#808080">//当procState>= 16时,</span>
     <span style="color:#cc7832">if</span> (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
         <span style="color:#cc7832">if</span> (app.hasClientActivities) {
             <span style="color:#808080">//当进程存在client activity,则设置procState=15;</span>
             procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
             app.adjType = <span style="color:#6a8759">"cch-client-act"</span>;
         } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (app.treatLikeActivity) {
             <span style="color:#808080">//当进程可以像activity一样对待时,则设置procState=14;</span>
             procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
             app.adjType = <span style="color:#6a8759">"cch-as-act"</span>;
         }
     }
    
     <span style="color:#808080">//当adj = 5时</span>
     <span style="color:#cc7832">if</span> (adj == ProcessList.SERVICE_ADJ) {
         <span style="color:#cc7832">if</span> (doingAll) {
             <span style="color:#808080">//当A类Service个数 > service/3时,则加入到B类Service</span>
             app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/<span style="color:#6897bb">3</span>);
             mNewNumServiceProcs++;
             <span style="color:#cc7832">if</span> (!app.serviceb) {
                 <span style="color:#808080">//当对于低RAM设备,则把该service直接放入B类Service</span>
                 <span style="color:#cc7832">if</span> (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
                         && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
                     app.serviceHighRam = <span style="color:#cc7832">true</span>;
                     app.serviceb = <span style="color:#cc7832">true</span>;
                 } <span style="color:#cc7832">else</span> {
                     mNewNumAServiceProcs++;
                 }
             } <span style="color:#cc7832">else</span> {
                 app.serviceHighRam = <span style="color:#cc7832">false</span>;
             }
         }
         <span style="color:#808080">//调整adj=8</span>
         <span style="color:#cc7832">if</span> (app.serviceb) {
             adj = ProcessList.SERVICE_B_ADJ;
         }
     }
     <span style="color:#808080">//将计算得到的adj赋给curRawAdj</span>
     app.curRawAdj = adj;
    
     <span style="color:#808080">//当adj大小上限为maxAdj</span>
     <span style="color:#cc7832">if</span> (adj > app.maxAdj) {
         adj = app.maxAdj;
         <span style="color:#cc7832">if</span> (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
             schedGroup = Process.THREAD_GROUP_DEFAULT;
         }
     }
     <span style="color:#808080">//对于hasAboveClient=true,则降低该进程adj</span>
     app.curAdj = app.modifyRawOomAdj(adj);
     app.curSchedGroup = schedGroup;
     app.curProcState = procState;
     app.foregroundActivities = foregroundActivities;
     <span style="color:#808080">//返回进程的curRawAdj</span>
     <span style="color:#cc7832">return</span> app.curRawAdj;  }
    </code></span></span>

    13.小节

    主要工作:计算进展的adj和procState

    • 进展为空的情况
    • maxAdj <= 0
    • 计算各种状态下(当前显示活动,症结接收的广播/服务等)的adj和procState
    • 非前台activity的情况
    • adj> 2的情况
    • HeavyWeightProces情况
    • HomeProcess情况
    • 上一个过程情况
    • 备份进程情况
    • 服务情况
    • ContentProvider情况
    • 调整adj

    原则1:取大优先权,Android给进程优先级评级策略是选择最高的优先级,例如:当进程既有后台服务,也有前台Activity时,该进程的优先级规模为前台进展(adj = 0 ),而非服务进程(adj = 5)。

    原则2:一个进程的等级可能会因其他进程对它的依赖而有所提高,即服务于另一进程的进程其等级永远不会低于其所服务的进程。例如,如果进程A的ContentProvider为进度B的客户端提供服务,或者如果进度A中的服务绑定到进度B的组件,则进程A的必然至少与进度B替代。

    五。applyOomAdjLocked

    5.1原始码

    <span style="color:#404040"><span style="color:#333333"><code><span style="color:#cc7832">private</span> <span style="color:#cc7832">final</span> <span style="color:#cc7832">boolean</span> <span style="color:#ffc66d">applyOomAdjLocked</span>(ProcessRecord app, <span style="color:#cc7832">boolean</span> doingAll, <span style="color:#cc7832">long</span> now, <span style="color:#cc7832">long</span> nowElapsed) {
        <span style="color:#cc7832">boolean</span> success = <span style="color:#cc7832">true</span>;
    
        <span style="color:#808080">//将curRawAdj赋给setRawAdj</span>
        <span style="color:#cc7832">if</span> (app.curRawAdj != app.setRawAdj) {
            app.setRawAdj = app.curRawAdj;
        }
    
        <span style="color:#cc7832">if</span> (app.curAdj != app.setAdj) {
            <span style="color:#808080">//将adj值 发送给lmkd守护进程</span>
            ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
            app.setAdj = app.curAdj;
        }
    
        <span style="color:#808080">//情况为: waitingToKill</span>
        <span style="color:#cc7832">if</span> (app.setSchedGroup != app.curSchedGroup) {
            app.setSchedGroup = app.curSchedGroup;
            <span style="color:#cc7832">if</span> (app.waitingToKill != <span style="color:#cc7832">null</span> && app.curReceiver == <span style="color:#cc7832">null</span>
                    && app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
                <span style="color:#808080">//杀进程,并设置applyOomAdjLocked过程失败</span>
                app.kill(app.waitingToKill, <span style="color:#cc7832">true</span>);
                success = <span style="color:#cc7832">false</span>;
            } <span style="color:#cc7832">else</span> {
                <span style="color:#cc7832">long</span> oldId = Binder.clearCallingIdentity();
                <span style="color:#cc7832">try</span> {
                    <span style="color:#808080">//设置进程组信息</span>
                    Process.setProcessGroup(app.pid, app.curSchedGroup);
                } <span style="color:#cc7832">catch</span> (Exception e) {
                } <span style="color:#cc7832">finally</span> {
                    Binder.restoreCallingIdentity(oldId);
                }
                <span style="color:#808080">//调整进程的swappiness值</span>
                Process.setSwappiness(app.pid,
                        app.curSchedGroup <= Process.THREAD_GROUP_BG_NONINTERACTIVE);
            }
        }
        <span style="color:#cc7832">if</span> (app.repForegroundActivities != app.foregroundActivities) {
            app.repForegroundActivities = app.foregroundActivities;
            changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
        }
        <span style="color:#cc7832">if</span> (app.repProcState != app.curProcState) {
            app.repProcState = app.curProcState;
            changes |= ProcessChangeItem.CHANGE_PROCESS_STATE;
            <span style="color:#cc7832">if</span> (app.thread != <span style="color:#cc7832">null</span>) {
                <span style="color:#808080">//设置进程状态</span>
                app.thread.setProcessState(app.repProcState);
            }
        }
    
        <span style="color:#cc7832">if</span> (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
                || ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) {
            app.lastStateTime = now;
            <span style="color:#808080">//当setProcState = -1或者curProcState与setProcState值不同时,则计算pss下次时间(参数true)</span>
            app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, <span style="color:#cc7832">true</span>,
                    mTestPssMode, isSleeping(), now);
        } <span style="color:#cc7832">else</span> {
            当前时间超过pss下次时间,则请求统计pss,并计算pss下次时间(参数<span style="color:#cc7832">false</span>)
            <span style="color:#cc7832">if</span> (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL)
                    && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
                    mTestPssMode)))) {
                requestPssLocked(app, app.setProcState);
                app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, <span style="color:#cc7832">false</span>,
                        mTestPssMode, isSleeping(), now);
            }
        }
    
        <span style="color:#cc7832">if</span> (app.setProcState != app.curProcState) {
            <span style="color:#cc7832">boolean</span> setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
            <span style="color:#cc7832">boolean</span> curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
            <span style="color:#cc7832">if</span> (setImportant && !curImportant) {
                BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
                <span style="color:#cc7832">synchronized</span> (stats) {
                    app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
                            app.pid, nowElapsed);
                }
                app.lastCpuTime = app.curCpuTime;
    
            }
            maybeUpdateUsageStatsLocked(app, nowElapsed);
    
            app.setProcState = app.curProcState;
            <span style="color:#cc7832">if</span> (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
                app.notCachedSinceIdle = <span style="color:#cc7832">false</span>;
            }
            <span style="color:#cc7832">if</span> (!doingAll) {
                setProcessTrackerStateLocked(app, mProcessStats.getMemFactorLocked(), now);
            } <span style="color:#cc7832">else</span> {
                app.procStateChanged = <span style="color:#cc7832">true</span>;
            }
        } <span style="color:#cc7832">else</span> <span style="color:#cc7832">if</span> (app.reportedInteraction && (nowElapsed-app.interactionEventTime)
                > USAGE_STATS_INTERACTION_INTERVAL) {
            maybeUpdateUsageStatsLocked(app, nowElapsed);
        }
    
        <span style="color:#cc7832">if</span> (changes != <span style="color:#6897bb">0</span>) {
            <span style="color:#cc7832">int</span> i = mPendingProcessChanges.size()-<span style="color:#6897bb">1</span>;
            ProcessChangeItem item = <span style="color:#cc7832">null</span>;
            <span style="color:#cc7832">while</span> (i >= <span style="color:#6897bb">0</span>) {
                item = mPendingProcessChanges.get(i);
                <span style="color:#cc7832">if</span> (item.pid == app.pid) {
                    <span style="color:#cc7832">break</span>;
                }
                i--;
            }
            <span style="color:#cc7832">if</span> (i < <span style="color:#6897bb">0</span>) {
                <span style="color:#cc7832">final</span> <span style="color:#cc7832">int</span> NA = mAvailProcessChanges.size();
                <span style="color:#cc7832">if</span> (NA > <span style="color:#6897bb">0</span>) {
                    item = mAvailProcessChanges.remove(NA-<span style="color:#6897bb">1</span>);
                } <span style="color:#cc7832">else</span> {
                    item = <span style="color:#cc7832">new</span> ProcessChangeItem();
                }
                item.changes = <span style="color:#6897bb">0</span>;
                item.pid = app.pid;
                item.uid = app.info.uid;
                <span style="color:#cc7832">if</span> (mPendingProcessChanges.size() == <span style="color:#6897bb">0</span>) {
                    mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
                }
                mPendingProcessChanges.add(item);
            }
            item.changes |= changes;
            item.processState = app.repProcState;
            item.foregroundActivities = app.repForegroundActivities;
        }
    
        <span style="color:#cc7832">return</span> success;
    }
    </code></span></span>

    5.2小节

    该方法主要功能:

    1. 把curRawAdj值赋给setRawAdj
    2. 把adj值发送给lmkd守护进程
    3. 当app标记waitingToKill,且没有广播接收器运行在该进程,并且调度组为后台非交互组,则杀掉该进程,设置applyOomAdjLocked过程失败;
    4. 设置进程组信息
    5. 设置进度状态
    6. 执行pss统计操作,以及计算下一次pss时间
    7. 设置进度状态改变;

    apply过程中只有当waitingToKill情况下杀掉该进程,则返回false;否则都是返回true。

    六,总结

    调整进度的adj的3大护法:updateOomAdjLocked是更新adj中最核心的方法,computeOomAdjLocked和applyOomAdjLocked方法是供updateOomAdjLocked所调用的。

    • updateOomAdjLocked:更新adj,当目标进程为空,或者被杀则返回false;否则返回true;
    • computeOomAdjLocked:计算adj,返回计算后RawAdj值;
    • applyOomAdjLocked:应用adj,当需要杀掉目标进程则返回false;否则返回true。

    6.1 computeOomAdjLocked

    计算进度的curAdj(位于文件ProcessList.java)和curProcState(位于文件ActivityManager.java)

    情况一:

    案件进度类型当前组
    1个空进程背景
    2maxAdj <= 0进度默认
    2maxAdj <= 0 && TOP_APPTOP_APP
    3TOP_APPTOP_APP
    4isReceivingBroadcast默认/背景
    5执行服务默认/背景
    6以上皆不是背景
    6以上皆不是&&被杀的home进程默认
    7非前台活动&& r.visible默认
    7非前台活动&& r.state为暂停/暂停默认
    7非前台活动&& r.state为停止--
    7非前台activity &&以上皆不是--
    8adj> 2或procState> 4情况&& app.foregroundServices默认
    8adj> 2或procState> 4情况&& app.forcingToForeground默认
    9mHeavyWeightProcess背景
    10mHomeProcess背景
    11mPreviousProcess && app.activities背景
    12mBackupTarget--

    THREAD_GROUP_xxx。

    情况一:

     进度类型adjTypecurAdjcurProcState
    1个app.thread ==空--CACHED_APP_MAX_ADJPROCESS_STATE_CACHED_EMPTY(16)
    2maxAdj <= 0进度固定maxAdjPROCESS_STATE_PERSISTENT(0)
    2maxAdj <= 0 && TOP_APP持久活动maxAdjPROCESS_STATE_PERSISTENT_UI(1)
    3TOP_APP顶级活动FOREGROUND_APP_ADJPROCESS_STATE_TOP(2)
    4isReceivingBroadcast广播FOREGROUND_APP_ADJPROCESS_STATE_RECEIVER(11)
    5执行服务执行服务FOREGROUND_APP_ADJPROCESS_STATE_SERVICE(10)
    6以上皆不是cachedAdjPROCESS_STATE_CACHED_EMPTY(16)
    6以上皆不是&&被杀的home进程顶级活动PERSISTENT_PROC_ADJPROCESS_STATE_CACHED_EMPTY(16)
    7非前台活动&& r.visible可见VISIBLE_APP_ADJPROCESS_STATE_TOP
    7非前台活动&& r.state为暂停/暂停暂停PERCEPTIBLE_APP_ADJPROCESS_STATE_TOP
    7非前台活动&& r.state为停止停止PERCEPTIBLE_APP_ADJPROCESS_STATE_LAST_ACTIVITY(13)
    7非前台activity &&以上皆不是行为--PROCESS_STATE_CACHED_ACTIVITY(14)
    8adj> 2或procState> 4情况&& app.foregroundServicesfg服务PERCEPTIBLE_APP_ADJPROCESS_STATE_FOREGROUND_SERVICE(4)
    8adj> 2或procState> 4情况&& app.forcingToForeground力-fgPERCEPTIBLE_APP_ADJPROCESS_STATE_IMPORTANT_FOREGROUND(6)
    9mHeavyWeightProcessHEAVY_WEIGHT_APP_ADJPROCESS_STATE_HEAVY_WEIGHT(9)
    10mHomeProcessHOME_APP_ADJPROCESS_STATE_HOME(12)
    11mPreviousProcess && app.activities以前PREVIOUS_APP_ADJPROCESS_STATE_LAST_ACTIVITY(13)
    12mBackupTarget后备BACKUP_APP_ADJPROCESS_STATE_BACKUP(8)

    情况二:服务

     进度类型adjTypecurAdjcurProcState
    13服务已启动&& hasShownUi &&调整> SERVICE_ADJcch-started-ui-services--PROCESS_STATE_SERVICE(10)
    13服务已启动&&无UI &&活动时间<30min启动服务SERVICE_ADJPROCESS_STATE_SERVICE(10)
    13服务已启动&&无UI &&活动时间> 30mincch启动的服务--PROCESS_STATE_SERVICE(10)

    情况三:提供者

    如果(procState> clientProcState){procState = clientProcState; }

    保证provider所在进程的优先级高于或等于客户端进程。所以appindex应该为top才对,使用结束后再恢复为空。

    incProviderCountLocked的过程是建立provider的连接。

    • 广播:前台广播物理则SCHED_GROUP_DEFAULT; 后台广播样本则为SCHED_GROUP_BACKGROUND
    • 服务:execServicesFg则SCHED_GROUP_DEFAULT; 后台服务则SCHED_GROUP_BACKGROUND
    • cachedAdj一般地都是大于或等于CACHED_APP_MIN_ADJ,很多情况下为UNKNOWN_ADJ;
    • cch-empty的情况下,进展的empty和cached都为true
    展开全文
    feelinghappy 2019-11-19 11:26:37
  • 1、p-value 单个假设检验中主要依靠p值(或统计量t)做出是否拒绝零假设H0的决定:p-value和预先设定的检验水准 α 做对比,如果p-value小于等于α,拒绝原假设,否则不拒绝原假设。 p-value:表征了在原假设成立的...

    1、p-value

    单个假设检验中主要依靠p值(或统计量t)做出是否拒绝零假设H0的决定:p-value和预先设定的检验水准 α 做对比,如果p-value小于等于α,拒绝原假设,否则不拒绝原假设。

    • p-value:表征了在原假设成立的条件下,重复进行当前的试验,获得现有统计量t及其更极端情况的概率。
    • 给定检验水准 α 时,可得出对应的拒绝域;根据当前试验,可以计算出 p-value 。当 p-value 越小时,表示此时试验得到的统计量t越落在拒绝域。因此基于 p-value 的结果等价于基于t值的结果。因此,p-value 越小,拒绝原假设的信心越大。
    • 假阳性率:false positive rate, FPR.检验水准α给出了事先犯I-型错误的最大概率。

    2、多重假设检验和总体错误率

    在进行多重假设检验时,每个单独的假设都具有其本身的I型错误。在这种情况下,如果不进行任何的控制,犯I-型错误的概率会随着假设检验的个数而迅速增加。
    多重假设检验中,广泛使用的错误控制指标是总体错误率(family-wise error rate,FWER),即至少出现一次错误地拒绝真实H0的可能性;FWER小于等于alpha。而研究者更关心的是能否尽量多地识别出差异表达的基因,并且能够容忍和允许总的拒绝中发生少量的错误识别,称为错误发现false discovery。即需要在错误发现和总的拒绝次数R之间寻找一种平衡,即在检验出尽可能多的候选变量的同时将错误发现率控制在一个可以接受的范围。

    • 错误发现率(False Discovery Rate,FDR),表示了在所有R次拒绝中错误发现的期望比例。错误发现率和假阳性率之间有着本质的差别。错误发现率将范围限定在总的拒绝次数中;而假阳性率则针对所有变量数而言。
      给定FDR的控制水平α,多重假设检验次数M,通过求得拒绝H0的次数N,可得出多重检验M次中,有多少次是被错误识别的(=α * N)。Benjamini和Hochberg给出了一个基于p-value的逐步向下控制程序,用于求出拒绝H0的次数N的值。并且证明在BH控制下,FDR 小于等于 α。

    3、FDR校正后的p-value,即q-value

    • 用FDR错误控制法对p-value作多重假设检验校正

    FDR错误控制法是Benjamini于1995年提出一种方法,通过控制FDR(False Discovery Rate)来决定P值的域值. 假设你挑选了R个差异表达的基因,其中有S个是真正有差异表达的,另外有V个其实是没有差异表达的,是假阳性的。实践中希望错误比例Q=V/R平均而言不 能超过某个预先设定的值(比如0.05),在统计学上,这也就等价于控制FDR不能超过5%.

    对所有候选基因的p值进行从小到大排序,则若想控制fdr不能超过q,则只需找到最大的正整数i,使得 p(i)<= (i*q)/m.然后,挑选对应p(1),p(2),...,p(i)的基因做为差异表达基因,这样就能从统计学上保证fdr不超过q。
    因此,FDR的计算公式如下:

    q-value(i)=p(i)*length(p)/rank(p)

    展开全文
    wt141643 2020-03-26 20:51:42
  • perfectnihil 2019-05-26 20:02:41
  • he980725866 2021-03-17 21:12:54
  • qq_26309777 2020-06-17 23:46:07
  • u014467816 2021-01-14 16:32:25
  • StarfishCu 2021-03-16 13:00:20
  • weixin_29492649 2021-05-11 16:21:43
  • weixin_34337265 2018-04-13 22:18:00
  • w2064004678 2020-07-08 13:16:40
  • u012964796 2017-03-14 19:27:38
  • mingtiannihao623 2021-08-19 20:52:41
  • zhangbijun1230 2018-08-01 20:39:13
  • hacker_crazy 2018-10-19 16:03:22
  • hello_json 2017-05-25 16:24:36
  • zhoumushui 2016-04-20 14:24:41
  • weixin_42364855 2021-05-03 03:10:11
  • CCJHDOPC 2016-10-14 18:10:51
  • woodcorpse 2018-02-18 13:34:20
  • csdn_eric_zhao 2016-12-29 10:44:07
  • weixin_39925939 2021-11-15 11:40:39
  • csh86277516 2017-01-22 16:48:48
  • czmmiao 2014-06-27 22:42:41

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,701
精华内容 4,280
关键字:

adjvalue