FileDocCategorySizeDatePackage
ProcessList.javaAPI DocAndroid 5.1 API30520Thu Mar 12 22:22:42 GMT 2015com.android.server.am

ProcessList

public final class ProcessList extends Object
Activity manager code dealing with processes.

Fields Summary
static final int
MIN_CRASH_INTERVAL
static final int
UNKNOWN_ADJ
static final int
CACHED_APP_MAX_ADJ
static final int
CACHED_APP_MIN_ADJ
static final int
SERVICE_B_ADJ
static final int
PREVIOUS_APP_ADJ
static final int
HOME_APP_ADJ
static final int
SERVICE_ADJ
static final int
HEAVY_WEIGHT_APP_ADJ
static final int
BACKUP_APP_ADJ
static final int
PERCEPTIBLE_APP_ADJ
static final int
VISIBLE_APP_ADJ
static final int
FOREGROUND_APP_ADJ
static final int
PERSISTENT_SERVICE_ADJ
static final int
PERSISTENT_PROC_ADJ
static final int
SYSTEM_ADJ
static final int
NATIVE_ADJ
static final int
PAGE_SIZE
static final int
MIN_CACHED_APPS
static final int
MAX_CACHED_APPS
static final long
MAX_EMPTY_TIME
private static final int
MAX_EMPTY_APPS
static final int
TRIM_EMPTY_APPS
static final int
TRIM_CACHED_APPS
static final int
TRIM_CRITICAL_THRESHOLD
static final int
TRIM_LOW_THRESHOLD
static final byte
LMK_TARGET
static final byte
LMK_PROCPRIO
static final byte
LMK_PROCREMOVE
private final int[]
mOomAdj
private final int[]
mOomMinFreeLow
private final int[]
mOomMinFreeHigh
private final int[]
mOomMinFree
private final long
mTotalMemMb
private long
mCachedRestoreLevel
private boolean
mHaveDisplaySize
private static android.net.LocalSocket
sLmkdSocket
private static OutputStream
sLmkdOutputStream
public static final int
PSS_SAFE_TIME_FROM_STATE_CHANGE
public static final int
PSS_MIN_TIME_FROM_STATE_CHANGE
public static final int
PSS_MAX_INTERVAL
public static final int
PSS_ALL_INTERVAL
private static final int
PSS_SHORT_INTERVAL
private static final int
PSS_FIRST_TOP_INTERVAL
private static final int
PSS_FIRST_BACKGROUND_INTERVAL
private static final int
PSS_FIRST_CACHED_INTERVAL
private static final int
PSS_SAME_IMPORTANT_INTERVAL
private static final int
PSS_SAME_SERVICE_INTERVAL
private static final int
PSS_SAME_CACHED_INTERVAL
public static final int
PSS_TEST_MIN_TIME_FROM_STATE_CHANGE
private static final int
PSS_TEST_FIRST_TOP_INTERVAL
private static final int
PSS_TEST_FIRST_BACKGROUND_INTERVAL
private static final int
PSS_TEST_SAME_IMPORTANT_INTERVAL
private static final int
PSS_TEST_SAME_BACKGROUND_INTERVAL
public static final int
PROC_MEM_PERSISTENT
public static final int
PROC_MEM_TOP
public static final int
PROC_MEM_IMPORTANT
public static final int
PROC_MEM_SERVICE
public static final int
PROC_MEM_CACHED
private static final int[]
sProcStateToProcMem
private static final long[]
sFirstAwakePssTimes
private static final long[]
sSameAwakePssTimes
private static final long[]
sTestFirstAwakePssTimes
private static final long[]
sTestSameAwakePssTimes
Constructors Summary
ProcessList()


     
        MemInfoReader minfo = new MemInfoReader();
        minfo.readMemInfo();
        mTotalMemMb = minfo.getTotalSize()/(1024*1024);
        updateOomLevels(0, 0, false);
    
Methods Summary
public static voidappendRamKb(java.lang.StringBuilder sb, long ramKb)

        for (int j=0, fact=10; j<6; j++, fact*=10) {
            if (ramKb < fact) {
                sb.append(' ");
            }
        }
        sb.append(ramKb);
    
voidapplyDisplaySize(com.android.server.wm.WindowManagerService wm)

        if (!mHaveDisplaySize) {
            Point p = new Point();
            wm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, p);
            if (p.x != 0 && p.y != 0) {
                updateOomLevels(p.x, p.y, true);
                mHaveDisplaySize = true;
            }
        }
    
private static java.lang.StringbuildOomTag(java.lang.String prefix, java.lang.String space, int val, int base)

        if (val == base) {
            if (space == null) return prefix;
            return prefix + "  ";
        }
        return prefix + "+" + Integer.toString(val-base);
    
public static intcomputeEmptyProcessLimit(int totalProcessLimit)

        return totalProcessLimit/2;
    
public static longcomputeNextPssTime(int procState, boolean first, boolean test, boolean sleeping, long now)

        final long[] table = test
                ? (first
                        ? sTestFirstAwakePssTimes
                        : sTestSameAwakePssTimes)
                : (first
                        ? sFirstAwakePssTimes
                        : sSameAwakePssTimes);
        return now + table[procState];
    
longgetCachedRestoreThresholdKb()
Return the maximum pss size in kb that we consider a process acceptable to restore from its cached state for running in the background when RAM is low.

        return mCachedRestoreLevel;
    
longgetMemLevel(int adjustment)

        for (int i=0; i<mOomAdj.length; i++) {
            if (adjustment <= mOomAdj[i]) {
                return mOomMinFree[i] * 1024;
            }
        }
        return mOomMinFree[mOomAdj.length-1] * 1024;
    
public static java.lang.StringmakeOomAdjString(int setAdj)

        if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
            return buildOomTag("cch", "  ", setAdj, ProcessList.CACHED_APP_MIN_ADJ);
        } else if (setAdj >= ProcessList.SERVICE_B_ADJ) {
            return buildOomTag("svcb ", null, setAdj, ProcessList.SERVICE_B_ADJ);
        } else if (setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
            return buildOomTag("prev ", null, setAdj, ProcessList.PREVIOUS_APP_ADJ);
        } else if (setAdj >= ProcessList.HOME_APP_ADJ) {
            return buildOomTag("home ", null, setAdj, ProcessList.HOME_APP_ADJ);
        } else if (setAdj >= ProcessList.SERVICE_ADJ) {
            return buildOomTag("svc  ", null, setAdj, ProcessList.SERVICE_ADJ);
        } else if (setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
            return buildOomTag("hvy  ", null, setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
        } else if (setAdj >= ProcessList.BACKUP_APP_ADJ) {
            return buildOomTag("bkup ", null, setAdj, ProcessList.BACKUP_APP_ADJ);
        } else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
            return buildOomTag("prcp ", null, setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
        } else if (setAdj >= ProcessList.VISIBLE_APP_ADJ) {
            return buildOomTag("vis  ", null, setAdj, ProcessList.VISIBLE_APP_ADJ);
        } else if (setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
            return buildOomTag("fore ", null, setAdj, ProcessList.FOREGROUND_APP_ADJ);
        } else if (setAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
            return buildOomTag("psvc ", null, setAdj, ProcessList.PERSISTENT_SERVICE_ADJ);
        } else if (setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
            return buildOomTag("pers ", null, setAdj, ProcessList.PERSISTENT_PROC_ADJ);
        } else if (setAdj >= ProcessList.SYSTEM_ADJ) {
            return buildOomTag("sys  ", null, setAdj, ProcessList.SYSTEM_ADJ);
        } else if (setAdj >= ProcessList.NATIVE_ADJ) {
            return buildOomTag("ntv  ", null, setAdj, ProcessList.NATIVE_ADJ);
        } else {
            return Integer.toString(setAdj);
        }
    
public static java.lang.StringmakeProcStateString(int curProcState)

        String procState;
        switch (curProcState) {
            case -1:
                procState = "N ";
                break;
            case ActivityManager.PROCESS_STATE_PERSISTENT:
                procState = "P ";
                break;
            case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
                procState = "PU";
                break;
            case ActivityManager.PROCESS_STATE_TOP:
                procState = "T ";
                break;
            case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
                procState = "IF";
                break;
            case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
                procState = "IB";
                break;
            case ActivityManager.PROCESS_STATE_BACKUP:
                procState = "BU";
                break;
            case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
                procState = "HW";
                break;
            case ActivityManager.PROCESS_STATE_SERVICE:
                procState = "S ";
                break;
            case ActivityManager.PROCESS_STATE_RECEIVER:
                procState = "R ";
                break;
            case ActivityManager.PROCESS_STATE_HOME:
                procState = "HO";
                break;
            case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
                procState = "LA";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                procState = "CA";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                procState = "Ca";
                break;
            case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                procState = "CE";
                break;
            default:
                procState = "??";
                break;
        }
        return procState;
    
public static longminTimeFromStateChange(boolean test)

        return test ? PSS_TEST_MIN_TIME_FROM_STATE_CHANGE : PSS_MIN_TIME_FROM_STATE_CHANGE;
    
private static booleanopenLmkdSocket()

        try {
            sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
            sLmkdSocket.connect(
                new LocalSocketAddress("lmkd",
                        LocalSocketAddress.Namespace.RESERVED));
            sLmkdOutputStream = sLmkdSocket.getOutputStream();
        } catch (IOException ex) {
            Slog.w(ActivityManagerService.TAG,
                   "lowmemorykiller daemon socket open failed");
            sLmkdSocket = null;
            return false;
        }

        return true;
    
public static booleanprocStatesDifferForMem(int procState1, int procState2)


           
        return sProcStateToProcMem[procState1] != sProcStateToProcMem[procState2];
    
public static final voidremove(int pid)

        ByteBuffer buf = ByteBuffer.allocate(4 * 2);
        buf.putInt(LMK_PROCREMOVE);
        buf.putInt(pid);
        writeLmkd(buf);
    
public static final voidsetOomAdj(int pid, int uid, int amt)
Set the out-of-memory badness adjustment for a process.

param
pid The process identifier to set.
param
uid The uid of the app
param
amt Adjustment value -- lmkd allows -16 to +15. {@hide}

        if (amt == UNKNOWN_ADJ)
            return;

        long start = SystemClock.elapsedRealtime();
        ByteBuffer buf = ByteBuffer.allocate(4 * 4);
        buf.putInt(LMK_PROCPRIO);
        buf.putInt(pid);
        buf.putInt(uid);
        buf.putInt(amt);
        writeLmkd(buf);
        long now = SystemClock.elapsedRealtime();
        if ((now-start) > 250) {
            Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
                    + " = " + amt);
        }
    
private voidupdateOomLevels(int displayWidth, int displayHeight, boolean write)

        // Scale buckets from avail memory: at 300MB we use the lowest values to
        // 700MB or more for the top values.
        float scaleMem = ((float)(mTotalMemMb-350))/(700-350);

        // Scale buckets from screen size.
        int minSize = 480*800;  //  384000
        int maxSize = 1280*800; // 1024000  230400 870400  .264
        float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
        if (false) {
            Slog.i("XXXXXX", "scaleMem=" + scaleMem);
            Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth
                    + " dh=" + displayHeight);
        }

        float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;
        if (scale < 0) scale = 0;
        else if (scale > 1) scale = 1;
        int minfree_adj = Resources.getSystem().getInteger(
                com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAdjust);
        int minfree_abs = Resources.getSystem().getInteger(
                com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute);
        if (false) {
            Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
        }

        final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;

        for (int i=0; i<mOomAdj.length; i++) {
            int low = mOomMinFreeLow[i];
            int high = mOomMinFreeHigh[i];
            if (is64bit) {
                // Increase the high min-free levels for cached processes for 64-bit
                if (i == 4) high = (high*3)/2;
                else if (i == 5) high = (high*7)/4;
            }
            mOomMinFree[i] = (int)(low + ((high-low)*scale));
        }

        if (minfree_abs >= 0) {
            for (int i=0; i<mOomAdj.length; i++) {
                mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i]
                        / mOomMinFree[mOomAdj.length - 1]);
            }
        }

        if (minfree_adj != 0) {
            for (int i=0; i<mOomAdj.length; i++) {
                mOomMinFree[i] += (int)((float)minfree_adj * mOomMinFree[i]
                        / mOomMinFree[mOomAdj.length - 1]);
                if (mOomMinFree[i] < 0) {
                    mOomMinFree[i] = 0;
                }
            }
        }

        // The maximum size we will restore a process from cached to background, when under
        // memory duress, is 1/3 the size we have reserved for kernel caches and other overhead
        // before killing background processes.
        mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024) / 3;

        // Ask the kernel to try to keep enough memory free to allocate 3 full
        // screen 32bpp buffers without entering direct reclaim.
        int reserve = displayWidth * displayHeight * 4 * 3 / 1024;
        int reserve_adj = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAdjust);
        int reserve_abs = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAbsolute);

        if (reserve_abs >= 0) {
            reserve = reserve_abs;
        }

        if (reserve_adj != 0) {
            reserve += reserve_adj;
            if (reserve < 0) {
                reserve = 0;
            }
        }

        if (write) {
            ByteBuffer buf = ByteBuffer.allocate(4 * (2*mOomAdj.length + 1));
            buf.putInt(LMK_TARGET);
            for (int i=0; i<mOomAdj.length; i++) {
                buf.putInt((mOomMinFree[i]*1024)/PAGE_SIZE);
                buf.putInt(mOomAdj[i]);
            }

            writeLmkd(buf);
            SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
        }
        // GB: 2048,3072,4096,6144,7168,8192
        // HC: 8192,10240,12288,14336,16384,20480
    
private static voidwriteLmkd(java.nio.ByteBuffer buf)


        for (int i = 0; i < 3; i++) {
            if (sLmkdSocket == null) {
                    if (openLmkdSocket() == false) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException ie) {
                        }
                        continue;
                    }
            }

            try {
                sLmkdOutputStream.write(buf.array(), 0, buf.position());
                return;
            } catch (IOException ex) {
                Slog.w(ActivityManagerService.TAG,
                       "Error writing to lowmemorykiller socket");

                try {
                    sLmkdSocket.close();
                } catch (IOException ex2) {
                }

                sLmkdSocket = null;
            }
        }