Android adj调整时的各类进程状态

1. dump一下进程的信息

使用adb shell dumpsys activity p可以将Android的各类进程状态信息打印出来,这通常对于分析进程的运行状态和adj有很大帮助

Process LRU list (sorted by oom_adj, 46 total, non-act at 6, non-svc at 6):
PERS #45: sys F/ /PER LCMN t: 0 1240:system/1000 (fixed)
PERS #46: pers T/ /PERU LCMN t: 0 1484:com.android.systemui/u0a113 (pers-top-ui)

如上面PERPERU代表什么意思呢?(本次讲解的主题,至于上面的其它信息最后一节会全部解释一下)

具体dump的代码(代码基于Android S)在:frameworks\base\services\core\java\com\android\server\am\ProcessList.java
其打印的是ProcessStateRecordmCurProcState(通过getCurProcState()获得)

   void dumpProcessesLSP(FileDescriptor fd, PrintWriter pw, String[] args,
            int opti, boolean dumpAll, String dumpPackage, int dumpAppId) {
        //...

        pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");

        //...
            dumpProcessOomList(pw, mService, mLruProcesses, "    ", "Proc", "PERS", false,
                    dumpPackage);
            //...
    }
    private static boolean dumpProcessOomList(PrintWriter pw,
            ActivityManagerService service, List<ProcessRecord> origList,
            String prefix, String normalLabel, String persistentLabel,
            boolean inclDetails, String dumpPackage) {
        //...
            final ProcessStateRecord state = r.mState;
            //...
            String procState = makeProcStateString(state.getCurProcState());
            //...
    }

    public static String makeProcStateString(int curProcState) {
        return ActivityManager.procStateToString(curProcState);
    }

2. ProcState的枚举值和打印字串的对应关系

具体在ActivityManager.java中有对应关系,到这里大家应该知道
system_serverPER代表PROCESS_STATE_PERSISTENT状态,systemuiPERU代表PROCESS_STATE_PERSISTENT_UI状态

    public static String procStateToString(int procState) {
        final String procStateStr;
        switch (procState) {
            case ActivityManager.PROCESS_STATE_PERSISTENT:
                procStateStr = "PER ";
                break;
            case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
                procStateStr = "PERU";
                break;
            case ActivityManager.PROCESS_STATE_TOP:
                procStateStr = "TOP ";
                break;
            case ActivityManager.PROCESS_STATE_BOUND_TOP:
                procStateStr = "BTOP";
                break;
            case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
                procStateStr = "FGS ";
                break;
            case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
                procStateStr = "BFGS";
                break;
            case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
                procStateStr = "IMPF";
                break;
            case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
                procStateStr = "IMPB";
                break;
            case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
                procStateStr = "TRNB";
                break;
            case ActivityManager.PROCESS_STATE_BACKUP:
                procStateStr = "BKUP";
                break;
            case ActivityManager.PROCESS_STATE_SERVICE:
                procStateStr = "SVC ";
                break;
            case ActivityManager.PROCESS_STATE_RECEIVER:
                procStateStr = "RCVR";
                break;
            case ActivityManager.PROCESS_STATE_TOP_SLEEPING:
                procStateStr = "TPSL";
                break;
            case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
                procStateStr = "HVY ";
                break;
            case ActivityManager.PROCESS_STATE_HOME:
                procStateStr = "HOME";
                break;
            case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
                procStateStr = "LAST";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                procStateStr = "CAC ";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                procStateStr = "CACC";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_RECENT:
                procStateStr = "CRE ";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                procStateStr = "CEM ";
                break;
            case ActivityManager.PROCESS_STATE_NONEXISTENT:
                procStateStr = "NONE";
                break;
            default:
                procStateStr = "??";
                break;
        }
        return procStateStr;
    }

    public static final int PROCESS_STATE_UNKNOWN = ProcessStateEnum.UNKNOWN;

    public static final int PROCESS_STATE_PERSISTENT = ProcessStateEnum.PERSISTENT;

    public static final int PROCESS_STATE_PERSISTENT_UI = ProcessStateEnum.PERSISTENT_UI;

    public static final int PROCESS_STATE_TOP = ProcessStateEnum.TOP;

    public static final int PROCESS_STATE_BOUND_TOP = ProcessStateEnum.BOUND_TOP;

    public static final int PROCESS_STATE_FOREGROUND_SERVICE = ProcessStateEnum.FOREGROUND_SERVICE;

    public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE =
            ProcessStateEnum.BOUND_FOREGROUND_SERVICE;

    public static final int PROCESS_STATE_IMPORTANT_FOREGROUND =
            ProcessStateEnum.IMPORTANT_FOREGROUND;

    public static final int PROCESS_STATE_IMPORTANT_BACKGROUND =
            ProcessStateEnum.IMPORTANT_BACKGROUND;

    public static final int PROCESS_STATE_TRANSIENT_BACKGROUND =
            ProcessStateEnum.TRANSIENT_BACKGROUND;

    public static final int PROCESS_STATE_BACKUP = ProcessStateEnum.BACKUP;

    public static final int PROCESS_STATE_SERVICE = ProcessStateEnum.SERVICE;

    public static final int PROCESS_STATE_RECEIVER = ProcessStateEnum.RECEIVER;

    public static final int PROCESS_STATE_TOP_SLEEPING = ProcessStateEnum.TOP_SLEEPING;

    public static final int PROCESS_STATE_HEAVY_WEIGHT = ProcessStateEnum.HEAVY_WEIGHT;

    public static final int PROCESS_STATE_HOME = ProcessStateEnum.HOME;

    public static final int PROCESS_STATE_LAST_ACTIVITY = ProcessStateEnum.LAST_ACTIVITY;

    public static final int PROCESS_STATE_CACHED_ACTIVITY = ProcessStateEnum.CACHED_ACTIVITY;

    public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT =
            ProcessStateEnum.CACHED_ACTIVITY_CLIENT;

    public static final int PROCESS_STATE_CACHED_RECENT = ProcessStateEnum.CACHED_RECENT;

    public static final int PROCESS_STATE_CACHED_EMPTY = ProcessStateEnum.CACHED_EMPTY;

    public static final int PROCESS_STATE_NONEXISTENT = ProcessStateEnum.NONEXISTENT;

3. ProcState的各类状态都是在什么时候设置,都代表什么意思

下面是关于ProcessStateRecordmCurProcState都是在哪些情况下会设置有解释,
这个其实和adj调整有密不可分的关系,大部分逻辑也是在ADJ调整的时候设置了adj的值、adj的状态、还有进程状态mCurProcState这三者一般都是密切相关的
这里先做一个记录

//frameworks\base\core\java\android\app\ProcessStateEnum.aidl
//各类进程状态,注意这个不是adj的值,是进程状态的值,
//一般情况越小代表进程状态优先级越高(但是有很多例外,
//如SERVICE、RECEIVER状态时优先级可以较高,先不要简单认为是绝对优先级)
enum ProcessStateEnum {
    //PROCESS_STATE_UNKNOWN未知状态
    UNKNOWN = -1,

    //PROCESS_STATE_PERSISTENT常驻内存进程
    //1. system_server系统服务,adj是SYSTEM_ADJ
    //2. 没有界面的常驻进程会设置,此时adj是常驻进程PERSISTENT_PROC_ADJ级别
    //3. service服务依赖:设置了BIND_ABOVE_CLIENT或者BIND_IMPORTANT,
    //而且clinet的adj小于PERSISTENT_SERVICE_ADJ会设置,
    //此时adj是常驻服务PERSISTENT_SERVICE_ADJ级别
    //(也就是所谓的Persistent Service)
    PERSISTENT = 0,

    //PROCESS_STATE_PERSISTENT_UI带有界面的常驻内存进程
    //目前只有常驻进程,且是当前topApp
    //或者有hasTopUi(mHasTopUi==true,目前只有systemui通过AMS设置)
    //或者getCachedHasVisibleActivities有可见的活动对象activity的时候,
    //且(非睡眠状态)(或者播放远端动画时),才会设置
    PERSISTENT_UI = 1,

    //PROCESS_STATE_TOP当前最顶端top的activity,
    //只有当前app时mTopApp(top的activity)而且非睡眠状态的时候才会设置为top
    //PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp,
    //这些状态需要从ActivityTaskManagerService获得
    TOP = 2,

    //PROCESS_STATE_BOUND_TOP绑定了前台进程
    //1.service服务依赖:client时PROCESS_STATE_TOP状态的时候会设置
    //2.provider依赖:client时PROCESS_STATE_TOP状态的时候会设置
    BOUND_TOP = 3,

    //PROCESS_STATE_FOREGROUND_SERVICE前台运行的服务,
    //1.运行instrumentation(如自动化测试中,
    //部分三方app也会使用(很少,有保活效果))的时候设置
    //2.或者当其有前台运行的服务hasForegroundServices=true
    //时会进行设置(这种情况时最普遍的情况),
    //adj会设置成PERCEPTIBLE_APP_ADJ用户可感知的
    FOREGROUND_SERVICE = 4,

    //PROCESS_STATE_BOUND_FOREGROUND_SERVICE绑定了前台的进程
    //(虽然说是服务,但是其实provider等也会设置该值)
    //1.常驻进程如果是top app或者top ui的进程或者存在可见的activity,
    //在唤醒时(如亮屏)设置是PROCESS_STATE_PERSISTENT_UI,
    //休眠(如灭屏)且非播放远端动画时设置的就是BOUND_FOREGROUND_SERVICE
    //2.service服务依赖:客户端的优先级比top还小,如系统服务和常驻进程,
    //且设置了BIND_FOREGROUND_SERVICE
    //或者唤醒时状态而且设置了BIND_FOREGROUND_SERVICE_WHILE_AWAKE时
    //会设置BOUND_FOREGROUND_SERVICE
    //3.provider依赖:客户端的状态优先级小于等于PROCESS_STATE_FOREGROUND_SERVICE,
    //且客户端的状态非PROCESS_STATE_TOP(如果是TOP则设置
    //PROCESS_STATE_BOUND_TOP)时设置BOUND_FOREGROUND_SERVICE
    BOUND_FOREGROUND_SERVICE = 5,

    //PROCESS_STATE_IMPORTANT_FOREGROUND重要的前台进程
    //1.在mHasOverlayUi=true的时候(覆盖的界面),如mAppOverlaySurfaces存在,
    //此时adj也是设置成PERCEPTIBLE_APP_ADJ用户可感知的
    //2.service服务依赖:客户端的优先级比top还小,如系统服务和常驻进程,
    //没有设置BIND_FOREGROUND_SERVICE/BIND_FOREGROUND_SERVICE_WHILE_AWAKE
    //或者设置了BIND_FOREGROUND_SERVICE_WHILE_AWAKE但是在睡眠状态时
    //会设置该值
    //3.provider原因(自身非依赖):cpr.hasExternalProcessHandles为true,
    //代表provider存在外部进程依赖的时候(如AMS的getContentProviderExternal
    //调用时),会设置该值
    IMPORTANT_FOREGROUND = 6,

    //PROCESS_STATE_IMPORTANT_BACKGROUND重要的后台进程
    //service服务依赖:如果设置了BIND_IMPORTANT_BACKGROUND(绑定重要后台)
    //的时候,且客户端状态优先级小于该值时,会设置该值(目前只有该种情况)
    IMPORTANT_BACKGROUND = 7,

    //PROCESS_STATE_TRANSIENT_BACKGROUND后台临时的一个状态(一般的含义,
    //如toasts)
    //1.如果设置了getForcingToImportant不为null(调用AMS的setProcessImportant
    //设置),会设置该状态,
    //而且adj是用户可感知的PERCEPTIBLE_APP_ADJ,例如toasts是这种情况
    //(NotificationManagerService中调用setProcessImportant)
    //2.AMS的mBackupTargets是该app,且其adj大于BACKUP_APP_ADJ,会设置该值
    //3.service服务依赖:如果设置了BIND_NOT_FOREGROUND(非前台绑定)
    //而且没有设置BIND_IMPORTANT_BACKGROUND(绑定重要后台)的时候,
    //且客户端状态优先级小于该值时,会设置该值
    TRANSIENT_BACKGROUND = 8,

    //AMS的mBackupTargets(备份的app)是该app,
    //其状态最低优先级是PROCESS_STATE_BACKUP
    BACKUP = 9,

    //PROCESS_STATE_SERVICE处于服务状态的进程
    //1.有正在执行任务exec-service的服务numberOfExecutingServices,
    //此时adj是FOREGROUND_APP_ADJ前台
    //2.运行的服务中startRequested启动请求的(started-services)
    SERVICE = 10,

    //PROCESS_STATE_RECEIVER
    //在广播队列中存在接收者的时候getCachedIsReceivingBroadcast,
    //此时adj是FOREGROUND_APP_ADJ前台
    RECEIVER = 11,

    //PROCESS_STATE_TOP_SLEEPING
    //休眠时会将top app的状态设置成该值(如top-sleeping)、
    //或者非top app在isRunningRemoteAnimation的时候且休眠的时候也会设置
    TOP_SLEEPING = 12,

    //PROCESS_STATE_HEAVY_WEIGHT重要的app
    //当app无法保存状态,如AndroidManifest.xml设置了
    //"android:cantSaveState="true",
    //由于其无法保存状态,故尽量不要杀死, 
    //而且系统默认只有一个mHeavyWeightProcess,如果多个进程有类似的状态,
    //那很可能是非原生修改),
    //同时adj最小也是HEAVY_WEIGHT_APP_ADJ,adj类型时"heavy"
    //同时系统配置了<feature name="android.software.cant_save_state" />
    //这个feature
    //默认是有FEATURE_CANT_SAVE_STATE这个feature的
    //dumpsys package f | grep "cant_save_state"
    HEAVY_WEIGHT = 13,

    //PROCESS_STATE_HOME 桌面app
    //如果是ActivityTaskManagerService中mHomeProcess,
    //那么会设置这种状态
    HOME = 14,

    //PROCESS_STATE_LAST_ACTIVITY上一个启动的app
    //1.如果是上一个activity在activityStopped(ActivityRecord中)之后
    //RootWindowContainer中updatePreviousProcess会更新
    //ActivityTaskManagerService的mPreviousProcess,
    //adj类型是"previous",adj是PREVIOUS_APP_ADJ
    //2.最近20s内使用的provider,adj类型是"recent-provider",
    //adj是PREVIOUS_APP_ADJ
    //3.正在停止的activity,OomAdjuster中
    //onStoppingActivity(WindowProcessController会探查activity的情况),
    //这个状态是activity正在停止,但是不是所有的allStoppingFinishing都停止了,
    //才会设置,adj类型是stop-activity,看起来是临时状态
    LAST_ACTIVITY = 15,

    //PROCESS_STATE_CACHED_ACTIVITY 缓存activity
    //1.WindowProcessController的computeOomAdjFromActivities中没有提取出
    //activity状态, 则设置该状态,并设置adj类型为cch-act
    //大致流程是computeOomAdjLSP(OomAdjuster)->
    //computeOomAdjFromActivitiesIfNecessary(ProcessStateRecord)
    //->computeOomAdjFromActivities(WindowProcessController)
    //->onOtherActivity(OomAdjuster)
    //2.service服务依赖:在service链接设置了BIND_TREAT_LIKE_ACTIVITY,
    //服务端psr则设置setTreatLikeActivity的标记位,
    //也就是服务端被认为是一个activity
    //此时如果computeOomAdjLSP到后面都没有将procState提升到
    //PROCESS_STATE_CACHED_EMPTY之上,那么就会设置这个状态,
    //adj类型为"cch-as-act"
    CACHED_ACTIVITY = 16,

    //PROCESS_STATE_CACHED_ACTIVITY_CLIENT 缓存的client客户端,
    //一般如果是服务的客户端包含activity才有可能设置这个状态
    //hasClientActivities链接service的客户端中有Activity(ActiveServices的
    //updateServiceClientActivitiesLocked中会设置),
    //而且computeOomAdjLSP到后面都没有将procState提升到
    //PROCESS_STATE_CACHED_EMPTY之上,那么就会设置这个状态
    CACHED_ACTIVITY_CLIENT = 17,

    //PROCESS_STATE_CACHED_RECENT 已经处于缓存状态,但是最近有启动过activity
    //如果getCachedHasRecentTasks返回true(有activity在最近任务mRecentTasks
    //中),那么最低状态就是设置这个,这个adj类型为"cch-rec"
    //realStartActivityLocked(ActivityTaskSupervisor)
    //->setProcess(ActivityRecord)
    //->setRootProcess(Task.java没有设置FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS时)
    //->addRecentTask(WindowProcessController)/mRecentTasks.add/
    //mHasRecentTasks = true
    CACHED_RECENT = 18,

    //PROCESS_STATE_CACHED_EMPTY 空进程的状态,
    //目前cached进程最常见的状态就是这个
    //1. 默认adj调整时,如果是空进程则初始化成该状态PROCESS_STATE_CACHED_EMPTY
    //2. 如果app.getThread() = null,没有ApplicationThread(应用线程),
    //那么也就设置该状态
    //3. service服务依赖:客户端client的状态大于等于
    //PROCESS_STATE_CACHED_ACTIVITY(也就是优先级低于等于
    //PROCESS_STATE_CACHED_ACTIVITY)时,
    //服务端也会考虑设置成该状态(前提是前面没有更高优先的状态设置过)
    //4. provider依赖:和service依赖一样,客户端client的状态大于等于
    //PROCESS_STATE_CACHED_ACTIVITY(也就是优先级低于等于
    //PROCESS_STATE_CACHED_ACTIVITY)时,
    //本地端也会考虑设置成该状态(前提是前面没有更高优先的状态设置过)
    CACHED_EMPTY = 19,

    //PROCESS_STATE_NONEXISTENT 默认的初始化状态,
    //在进程还未创建之前会是这种状态
    //ProcessStateRecord中m***ProcState默认初始化的状态,
    //下面是启动进程的时候的流程
    //startProcessLocked(ProcessList.java)->
    //在ProcessList的startProcess之前,会调用
    //newProcessRecordLocked(ProcessList.java)
    //-> new ProcessRecord -> new ProcessStateRecord
    NONEXISTENT = 20,
}

上面说的system_serversystemui现在可以进一步说明一下,至于其进程状态也是类似的

system_serverPER代表PROCESS_STATE_PERSISTENT状态: 一般是系统服务、没有界面的常驻进程、常驻进程服务Persistent Service(可以动态启动和停止)

systemuiPERU代表PROCESS_STATE_PERSISTENT_UI状态:常驻进程带有UI的时候(如下拉systemui的时候,systemui就会是这个状态)

其实systemui还经常出现下面2中状态
=> 不带界面的时候

PERS #45: pers F/ /PER LCMN t: 0 1484:com.android.systemui/u0a113 (fixed)

=> 灭屏幕后(从PERU(锁屏界面是systemui的)切换到BFGS(具体原因可以查看上面的BOUND_FOREGROUND_SERVICE注释))

PERS #45: pers R/ /BFGS LCMN t: 0 1484:com.android.systemui/u0a113 (pers-top-ui)

4. 剩下的其它信息

如下面的全部信息,这些信息对于了解手机当时运行状态非常有帮助,包括了很多有用的信息,如:在mLruProcesses中的位置、adj、cgroup分组、是否有前台activity、进程状态、内存状态、进程能力、pid、uid、进程名字、依赖关系等
PERS #36: sys F/ /PER LCMN t:15 1421:system/1000 (fixed)
PERS #35: pers F/ /PER LCMN t:15 1729:com.android.systemui/u0a110 (fixed)
Proc # 0: fg T/A/TOP LCMN t:15 13122:com.taobao.taobao/u0a219 (top-activity)
Proc #20: psvc F/ /PER LCMN t:15 3194:com.google.android.providers.media.module/u0a212 (service) com.google.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl<=Proc{1421:system/1000}
Proc #12: cch+ 5 b/ /CEM ---- t:80 12971:com.eg.android.AlipayGphone:tools/u0a221 (cch-empty)

这里再来说一下上面的全部意思吧,
1、" “是:传入dumpProcessOomList的” “,用于对齐
2、PERS或者Proc:如果是常驻进程则是"PERS”,非常驻进程则是"Proc"
3、#36::代表原有mLruProcesses的序列值,如一共37个应用,数组下标从0到36,此处36代表其是mLruProcesses的第0个元素
4、fg或者cch+ 5等:代表adj值,fg代表adj = 0,cch+ 5代表adj = 905,具体请查看ProcessList的makeOomAdjString
5、T/A/TOP等:第一个T代表cgroup分组是SCHED_GROUP_TOP_APP(top app), 第二个A代表hasForegroundActivities拥有前台activity,第三个TOP就是我们之前说的进程状态ProcState
6、LCMN:进程可以拥有定位、camara、打电话、网络的能力(注意这里是可以拥有),具体请查看printCapabilitiesSummary
7、t:15:当前进程的mTrimMemoryLevel,15代表ComponentCallbacks2的TRIM_MEMORY_RUNNING_CRITICAL,内存已经比较紧张了,该值用于回收内存和标定当前内存紧张程度
8、1421: 代表进程号,具体查看ProcessRecord的toShortString
9、system: 代表进程名字,具体查看ProcessRecord的toShortString
10、1000或者u0a110: 代表进程的uid,具体查看ProcessRecord的toShortString
11、top-activity: 代表adj的类型mAdjType
12、com.google.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl<=Proc{1421:system/1000}
代表adj依赖关系调整时的调整对象state.getAdjTarget() <= 调整原因state.getAdjSource()
如这里的调整对象是ExternalStorageServiceImpl,调整原因是system去绑定了这个服务

具体代码逻辑如下 =>


//ProcessList.java
   public static String makeOomAdjString(int setAdj, boolean compact) {
        if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
            return buildOomTag("cch", "cch", "   ", setAdj,
                    ProcessList.CACHED_APP_MIN_ADJ, compact);
        } else if (setAdj >= ProcessList.SERVICE_B_ADJ) {
            return buildOomTag("svcb  ", "svcb", null, setAdj,
                    ProcessList.SERVICE_B_ADJ, compact);
        } else if (setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
            return buildOomTag("prev  ", "prev", null, setAdj,
                    ProcessList.PREVIOUS_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.HOME_APP_ADJ) {
            return buildOomTag("home  ", "home", null, setAdj,
                    ProcessList.HOME_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.SERVICE_ADJ) {
            return buildOomTag("svc   ", "svc", null, setAdj,
                    ProcessList.SERVICE_ADJ, compact);
        } else if (setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
            return buildOomTag("hvy   ", "hvy", null, setAdj,
                    ProcessList.HEAVY_WEIGHT_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.BACKUP_APP_ADJ) {
            return buildOomTag("bkup  ", "bkup", null, setAdj,
                    ProcessList.BACKUP_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
            return buildOomTag("prcl  ", "prcl", null, setAdj,
                    ProcessList.PERCEPTIBLE_LOW_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
            return buildOomTag("prcm  ", "prcm", null, setAdj,
                    ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
            return buildOomTag("prcp  ", "prcp", null, setAdj,
                    ProcessList.PERCEPTIBLE_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.VISIBLE_APP_ADJ) {
            return buildOomTag("vis", "vis", "   ", setAdj,
                    ProcessList.VISIBLE_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
            return buildOomTag("fg ", "fg ", "   ", setAdj,
                    ProcessList.FOREGROUND_APP_ADJ, compact);
        } else if (setAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
            return buildOomTag("psvc  ", "psvc", null, setAdj,
                    ProcessList.PERSISTENT_SERVICE_ADJ, compact);
        } else if (setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
            return buildOomTag("pers  ", "pers", null, setAdj,
                    ProcessList.PERSISTENT_PROC_ADJ, compact);
        } else if (setAdj >= ProcessList.SYSTEM_ADJ) {
            return buildOomTag("sys   ", "sys", null, setAdj,
                    ProcessList.SYSTEM_ADJ, compact);
        } else if (setAdj >= ProcessList.NATIVE_ADJ) {
            return buildOomTag("ntv  ", "ntv", null, setAdj,
                    ProcessList.NATIVE_ADJ, compact);
        } else {
            return Integer.toString(setAdj);
        }
    }

    private static boolean dumpProcessOomList(PrintWriter pw,
            ActivityManagerService service, List<ProcessRecord> origList,
            String prefix, String normalLabel, String persistentLabel,
            boolean inclDetails, String dumpPackage) {

        ArrayList<Pair<ProcessRecord, Integer>> list = sortProcessOomList(origList, dumpPackage);
        if (list.isEmpty()) return false;

        final long curUptime = SystemClock.uptimeMillis();
        final long uptimeSince = curUptime - service.mLastPowerCheckUptime;

        for (int i = list.size() - 1; i >= 0; i--) {
            ProcessRecord r = list.get(i).first;
            final ProcessStateRecord state = r.mState;
            final ProcessServiceRecord psr = r.mServices;
            String oomAdj = makeOomAdjString(state.getSetAdj(), false);
            char schedGroup;
            switch (state.getSetSchedGroup()) {
                case SCHED_GROUP_BACKGROUND:
                    schedGroup = 'b';
                    break;
                case SCHED_GROUP_DEFAULT:
                    schedGroup = 'F';
                    break;
                case SCHED_GROUP_TOP_APP:
                    schedGroup = 'T';
                    break;
                case SCHED_GROUP_RESTRICTED:
                    schedGroup = 'R';
                    break;
                case SCHED_GROUP_TOP_APP_BOUND:
                    schedGroup = 'B';
                    break;
                default:
                    schedGroup = '?';
                    break;
            }
            char foreground;
            if (state.hasForegroundActivities()) {
                foreground = 'A';
            } else if (psr.hasForegroundServices()) {
                foreground = 'S';
            } else {
                foreground = ' ';
            }
            String procState = makeProcStateString(state.getCurProcState());
            pw.print(prefix);
            pw.print(r.isPersistent() ? persistentLabel : normalLabel);
            pw.print(" #");
            int num = (origList.size() - 1) - list.get(i).second;
            if (num < 10) pw.print(' ');
            pw.print(num);
            pw.print(": ");
            pw.print(oomAdj);
            pw.print(' ');
            pw.print(schedGroup);
            pw.print('/');
            pw.print(foreground);
            pw.print('/');
            pw.print(procState);
            pw.print(' ');
            ActivityManager.printCapabilitiesSummary(pw, state.getCurCapability());
            pw.print(' ');
            pw.print(" t:");
            if (r.mProfile.getTrimMemoryLevel() < 10) pw.print(' ');
            pw.print(r.mProfile.getTrimMemoryLevel());
            pw.print(' ');
            pw.print(r.toShortString());
            pw.print(" (");
            pw.print(state.getAdjType());
            pw.println(')');
            if (state.getAdjSource() != null || state.getAdjTarget() != null) {
                pw.print(prefix);
                pw.print("    ");
                if (state.getAdjTarget() instanceof ComponentName) {
                    pw.print(((ComponentName) state.getAdjTarget()).flattenToShortString());
                } else if (state.getAdjTarget() != null) {
                    pw.print(state.getAdjTarget().toString());
                } else {
                    pw.print("{null}");
                }
                pw.print("<=");
                if (state.getAdjSource() instanceof ProcessRecord) {
                    pw.print("Proc{");
                    pw.print(((ProcessRecord) state.getAdjSource()).toShortString());
                    pw.println("}");
                } else if (state.getAdjSource() != null) {
                    pw.println(state.getAdjSource().toString());
                } else {
                    pw.println("{null}");
                }
            }
            if (inclDetails) {
                pw.print(prefix);
                pw.print("    ");
                pw.print("oom: max="); pw.print(state.getMaxAdj());
                pw.print(" curRaw="); pw.print(state.getCurRawAdj());
                pw.print(" setRaw="); pw.print(state.getSetRawAdj());
                pw.print(" cur="); pw.print(state.getCurAdj());
                pw.print(" set="); pw.println(state.getSetAdj());
                pw.print(prefix);
                pw.print("    ");
                pw.print("state: cur="); pw.print(makeProcStateString(state.getCurProcState()));
                pw.print(" set="); pw.print(makeProcStateString(state.getSetProcState()));
                pw.print(" lastPss=");
                DebugUtils.printSizeValue(pw, r.mProfile.getLastPss() * 1024);
                pw.print(" lastSwapPss=");
                DebugUtils.printSizeValue(pw, r.mProfile.getLastSwapPss() * 1024);
                pw.print(" lastCachedPss=");
                DebugUtils.printSizeValue(pw, r.mProfile.getLastCachedPss() * 1024);
                pw.println();
                pw.print(prefix);
                pw.print("    ");
                pw.print("cached="); pw.print(state.isCached());
                pw.print(" empty="); pw.print(state.isEmpty());
                pw.print(" hasAboveClient="); pw.println(psr.hasAboveClient());

                if (state.getSetProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
                    long lastCpuTime = r.mProfile.mLastCpuTime.get();
                    if (lastCpuTime != 0 && uptimeSince > 0) {
                        long timeUsed = r.mProfile.mCurCpuTime.get() - lastCpuTime;
                        pw.print(prefix);
                        pw.print("    ");
                        pw.print("run cpu over ");
                        TimeUtils.formatDuration(uptimeSince, pw);
                        pw.print(" used ");
                        TimeUtils.formatDuration(timeUsed, pw);
                        pw.print(" (");
                        pw.print((timeUsed * 100) / uptimeSince);
                        pw.println("%)");
                    }
                }
            }
        }
        return true;
    }

//ActivityManager.java
    public static void printCapabilitiesSummary(PrintWriter pw, @ProcessCapability int caps) {
        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
        pw.print((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
    }
	
//ComponentCallbacks2.java
    /**
     * Level for {@link #onTrimMemory(int)}: the process is nearing the end
     * of the background LRU list, and if more memory isn't found soon it will
     * be killed.
     */
    static final int TRIM_MEMORY_COMPLETE = 80;
    
    /**
     * Level for {@link #onTrimMemory(int)}: the process is around the middle
     * of the background LRU list; freeing memory can help the system keep
     * other processes running later in the list for better overall performance.
     */
    static final int TRIM_MEMORY_MODERATE = 60;
    
    /**
     * Level for {@link #onTrimMemory(int)}: the process has gone on to the
     * LRU list.  This is a good opportunity to clean up resources that can
     * efficiently and quickly be re-built if the user returns to the app.
     */
    static final int TRIM_MEMORY_BACKGROUND = 40;
    
    /**
     * Level for {@link #onTrimMemory(int)}: the process had been showing
     * a user interface, and is no longer doing so.  Large allocations with
     * the UI should be released at this point to allow memory to be better
     * managed.
     */
    static final int TRIM_MEMORY_UI_HIDDEN = 20;

    /**
     * Level for {@link #onTrimMemory(int)}: the process is not an expendable
     * background process, but the device is running extremely low on memory
     * and is about to not be able to keep any background processes running.
     * Your running process should free up as many non-critical resources as it
     * can to allow that memory to be used elsewhere.  The next thing that
     * will happen after this is {@link #onLowMemory()} called to report that
     * nothing at all can be kept in the background, a situation that can start
     * to notably impact the user.
     */
    static final int TRIM_MEMORY_RUNNING_CRITICAL = 15;

    /**
     * Level for {@link #onTrimMemory(int)}: the process is not an expendable
     * background process, but the device is running low on memory.
     * Your running process should free up unneeded resources to allow that
     * memory to be used elsewhere.
     */
    static final int TRIM_MEMORY_RUNNING_LOW = 10;

    /**
     * Level for {@link #onTrimMemory(int)}: the process is not an expendable
     * background process, but the device is running moderately low on memory.
     * Your running process may want to release some unneeded resources for
     * use elsewhere.
     */
    static final int TRIM_MEMORY_RUNNING_MODERATE = 5;
	
//ProcessRecord.java
    public String toShortString() {
        final String shortStringName = mShortStringName;
        if (shortStringName != null) {
            return shortStringName;
        }
        StringBuilder sb = new StringBuilder(128);
        toShortString(sb);
        return mShortStringName = sb.toString();
    }

    void toShortString(StringBuilder sb) {
        sb.append(mPid);
        sb.append(':');
        sb.append(processName);
        sb.append('/');
        if (info.uid < Process.FIRST_APPLICATION_UID) {
            sb.append(uid);
        } else {
            sb.append('u');
            sb.append(userId);
            int appId = UserHandle.getAppId(info.uid);
            if (appId >= Process.FIRST_APPLICATION_UID) {
                sb.append('a');
                sb.append(appId - Process.FIRST_APPLICATION_UID);
            } else {
                sb.append('s');
                sb.append(appId);
            }
            if (uid != info.uid) {
                sb.append('i');
                sb.append(UserHandle.getAppId(uid) - Process.FIRST_ISOLATED_UID);
            }
        }
    }
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值