Home | History | Annotate | Download | only in am
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.am;
     18 
     19 import java.io.IOException;
     20 import java.io.OutputStream;
     21 import java.nio.ByteBuffer;
     22 
     23 import android.app.ActivityManager;
     24 import android.os.Build;
     25 import android.os.SystemClock;
     26 import com.android.internal.util.MemInfoReader;
     27 import com.android.server.wm.WindowManagerService;
     28 
     29 import android.content.res.Resources;
     30 import android.graphics.Point;
     31 import android.os.SystemProperties;
     32 import android.net.LocalSocketAddress;
     33 import android.net.LocalSocket;
     34 import android.util.Slog;
     35 import android.view.Display;
     36 
     37 /**
     38  * Activity manager code dealing with processes.
     39  */
     40 final class ProcessList {
     41     // The minimum time we allow between crashes, for us to consider this
     42     // application to be bad and stop and its services and reject broadcasts.
     43     static final int MIN_CRASH_INTERVAL = 60*1000;
     44 
     45     // OOM adjustments for processes in various states:
     46 
     47     // Adjustment used in certain places where we don't know it yet.
     48     // (Generally this is something that is going to be cached, but we
     49     // don't know the exact value in the cached range to assign yet.)
     50     static final int UNKNOWN_ADJ = 16;
     51 
     52     // This is a process only hosting activities that are not visible,
     53     // so it can be killed without any disruption.
     54     static final int CACHED_APP_MAX_ADJ = 15;
     55     static final int CACHED_APP_MIN_ADJ = 9;
     56 
     57     // The B list of SERVICE_ADJ -- these are the old and decrepit
     58     // services that aren't as shiny and interesting as the ones in the A list.
     59     static final int SERVICE_B_ADJ = 8;
     60 
     61     // This is the process of the previous application that the user was in.
     62     // This process is kept above other things, because it is very common to
     63     // switch back to the previous app.  This is important both for recent
     64     // task switch (toggling between the two top recent apps) as well as normal
     65     // UI flow such as clicking on a URI in the e-mail app to view in the browser,
     66     // and then pressing back to return to e-mail.
     67     static final int PREVIOUS_APP_ADJ = 7;
     68 
     69     // This is a process holding the home application -- we want to try
     70     // avoiding killing it, even if it would normally be in the background,
     71     // because the user interacts with it so much.
     72     static final int HOME_APP_ADJ = 6;
     73 
     74     // This is a process holding an application service -- killing it will not
     75     // have much of an impact as far as the user is concerned.
     76     static final int SERVICE_ADJ = 5;
     77 
     78     // This is a process with a heavy-weight application.  It is in the
     79     // background, but we want to try to avoid killing it.  Value set in
     80     // system/rootdir/init.rc on startup.
     81     static final int HEAVY_WEIGHT_APP_ADJ = 4;
     82 
     83     // This is a process currently hosting a backup operation.  Killing it
     84     // is not entirely fatal but is generally a bad idea.
     85     static final int BACKUP_APP_ADJ = 3;
     86 
     87     // This is a process only hosting components that are perceptible to the
     88     // user, and we really want to avoid killing them, but they are not
     89     // immediately visible. An example is background music playback.
     90     static final int PERCEPTIBLE_APP_ADJ = 2;
     91 
     92     // This is a process only hosting activities that are visible to the
     93     // user, so we'd prefer they don't disappear.
     94     static final int VISIBLE_APP_ADJ = 1;
     95 
     96     // This is the process running the current foreground app.  We'd really
     97     // rather not kill it!
     98     static final int FOREGROUND_APP_ADJ = 0;
     99 
    100     // This is a process that the system or a persistent process has bound to,
    101     // and indicated it is important.
    102     static final int PERSISTENT_SERVICE_ADJ = -11;
    103 
    104     // This is a system persistent process, such as telephony.  Definitely
    105     // don't want to kill it, but doing so is not completely fatal.
    106     static final int PERSISTENT_PROC_ADJ = -12;
    107 
    108     // The system process runs at the default adjustment.
    109     static final int SYSTEM_ADJ = -16;
    110 
    111     // Special code for native processes that are not being managed by the system (so
    112     // don't have an oom adj assigned by the system).
    113     static final int NATIVE_ADJ = -17;
    114 
    115     // Memory pages are 4K.
    116     static final int PAGE_SIZE = 4*1024;
    117 
    118     // The minimum number of cached apps we want to be able to keep around,
    119     // without empty apps being able to push them out of memory.
    120     static final int MIN_CACHED_APPS = 2;
    121 
    122     // The maximum number of cached processes we will keep around before killing them.
    123     // NOTE: this constant is *only* a control to not let us go too crazy with
    124     // keeping around processes on devices with large amounts of RAM.  For devices that
    125     // are tighter on RAM, the out of memory killer is responsible for killing background
    126     // processes as RAM is needed, and we should *never* be relying on this limit to
    127     // kill them.  Also note that this limit only applies to cached background processes;
    128     // we have no limit on the number of service, visible, foreground, or other such
    129     // processes and the number of those processes does not count against the cached
    130     // process limit.
    131     static final int MAX_CACHED_APPS = 32;
    132 
    133     // We allow empty processes to stick around for at most 30 minutes.
    134     static final long MAX_EMPTY_TIME = 30*60*1000;
    135 
    136     // The maximum number of empty app processes we will let sit around.
    137     private static final int MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS);
    138 
    139     // The number of empty apps at which we don't consider it necessary to do
    140     // memory trimming.
    141     static final int TRIM_EMPTY_APPS = MAX_EMPTY_APPS/2;
    142 
    143     // The number of cached at which we don't consider it necessary to do
    144     // memory trimming.
    145     static final int TRIM_CACHED_APPS = (MAX_CACHED_APPS-MAX_EMPTY_APPS)/3;
    146 
    147     // Threshold of number of cached+empty where we consider memory critical.
    148     static final int TRIM_CRITICAL_THRESHOLD = 3;
    149 
    150     // Threshold of number of cached+empty where we consider memory critical.
    151     static final int TRIM_LOW_THRESHOLD = 5;
    152 
    153     // Low Memory Killer Daemon command codes.
    154     // These must be kept in sync with the definitions in lmkd.c
    155     //
    156     // LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs)
    157     // LMK_PROCPRIO <pid> <prio>
    158     // LMK_PROCREMOVE <pid>
    159     static final byte LMK_TARGET = 0;
    160     static final byte LMK_PROCPRIO = 1;
    161     static final byte LMK_PROCREMOVE = 2;
    162 
    163     // These are the various interesting memory levels that we will give to
    164     // the OOM killer.  Note that the OOM killer only supports 6 slots, so we
    165     // can't give it a different value for every possible kind of process.
    166     private final int[] mOomAdj = new int[] {
    167             FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
    168             BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ
    169     };
    170     // These are the low-end OOM level limits.  This is appropriate for an
    171     // HVGA or smaller phone with less than 512MB.  Values are in KB.
    172     private final int[] mOomMinFreeLow = new int[] {
    173             12288, 18432, 24576,
    174             36864, 43008, 49152
    175     };
    176     // These are the high-end OOM level limits.  This is appropriate for a
    177     // 1280x800 or larger screen with around 1GB RAM.  Values are in KB.
    178     private final int[] mOomMinFreeHigh = new int[] {
    179             73728, 92160, 110592,
    180             129024, 225000, 325000
    181     };
    182     // The actual OOM killer memory levels we are using.
    183     private final int[] mOomMinFree = new int[mOomAdj.length];
    184 
    185     private final long mTotalMemMb;
    186 
    187     private long mCachedRestoreLevel;
    188 
    189     private boolean mHaveDisplaySize;
    190 
    191     private static LocalSocket sLmkdSocket;
    192     private static OutputStream sLmkdOutputStream;
    193 
    194     ProcessList() {
    195         MemInfoReader minfo = new MemInfoReader();
    196         minfo.readMemInfo();
    197         mTotalMemMb = minfo.getTotalSize()/(1024*1024);
    198         updateOomLevels(0, 0, false);
    199     }
    200 
    201     void applyDisplaySize(WindowManagerService wm) {
    202         if (!mHaveDisplaySize) {
    203             Point p = new Point();
    204             wm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, p);
    205             if (p.x != 0 && p.y != 0) {
    206                 updateOomLevels(p.x, p.y, true);
    207                 mHaveDisplaySize = true;
    208             }
    209         }
    210     }
    211 
    212     private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
    213         // Scale buckets from avail memory: at 300MB we use the lowest values to
    214         // 700MB or more for the top values.
    215         float scaleMem = ((float)(mTotalMemMb-300))/(700-300);
    216 
    217         // Scale buckets from screen size.
    218         int minSize = 480*800;  //  384000
    219         int maxSize = 1280*800; // 1024000  230400 870400  .264
    220         float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
    221         if (false) {
    222             Slog.i("XXXXXX", "scaleMem=" + scaleMem);
    223             Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth
    224                     + " dh=" + displayHeight);
    225         }
    226 
    227         float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;
    228         if (scale < 0) scale = 0;
    229         else if (scale > 1) scale = 1;
    230         int minfree_adj = Resources.getSystem().getInteger(
    231                 com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAdjust);
    232         int minfree_abs = Resources.getSystem().getInteger(
    233                 com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute);
    234         if (false) {
    235             Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
    236         }
    237 
    238         if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
    239             // Increase the high min-free levels for cached processes for 64-bit
    240             mOomMinFreeHigh[4] = 225000;
    241             mOomMinFreeHigh[5] = 325000;
    242         }
    243 
    244         for (int i=0; i<mOomAdj.length; i++) {
    245             int low = mOomMinFreeLow[i];
    246             int high = mOomMinFreeHigh[i];
    247             mOomMinFree[i] = (int)(low + ((high-low)*scale));
    248         }
    249 
    250         if (minfree_abs >= 0) {
    251             for (int i=0; i<mOomAdj.length; i++) {
    252                 mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i]
    253                         / mOomMinFree[mOomAdj.length - 1]);
    254             }
    255         }
    256 
    257         if (minfree_adj != 0) {
    258             for (int i=0; i<mOomAdj.length; i++) {
    259                 mOomMinFree[i] += (int)((float)minfree_adj * mOomMinFree[i]
    260                         / mOomMinFree[mOomAdj.length - 1]);
    261                 if (mOomMinFree[i] < 0) {
    262                     mOomMinFree[i] = 0;
    263                 }
    264             }
    265         }
    266 
    267         // The maximum size we will restore a process from cached to background, when under
    268         // memory duress, is 1/3 the size we have reserved for kernel caches and other overhead
    269         // before killing background processes.
    270         mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024) / 3;
    271 
    272         // Ask the kernel to try to keep enough memory free to allocate 3 full
    273         // screen 32bpp buffers without entering direct reclaim.
    274         int reserve = displayWidth * displayHeight * 4 * 3 / 1024;
    275         int reserve_adj = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAdjust);
    276         int reserve_abs = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAbsolute);
    277 
    278         if (reserve_abs >= 0) {
    279             reserve = reserve_abs;
    280         }
    281 
    282         if (reserve_adj != 0) {
    283             reserve += reserve_adj;
    284             if (reserve < 0) {
    285                 reserve = 0;
    286             }
    287         }
    288 
    289         if (write) {
    290             ByteBuffer buf = ByteBuffer.allocate(4 * (2*mOomAdj.length + 1));
    291             buf.putInt(LMK_TARGET);
    292             for (int i=0; i<mOomAdj.length; i++) {
    293                 buf.putInt((mOomMinFree[i]*1024)/PAGE_SIZE);
    294                 buf.putInt(mOomAdj[i]);
    295             }
    296 
    297             writeLmkd(buf);
    298             SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
    299         }
    300         // GB: 2048,3072,4096,6144,7168,8192
    301         // HC: 8192,10240,12288,14336,16384,20480
    302     }
    303 
    304     public static int computeEmptyProcessLimit(int totalProcessLimit) {
    305         return totalProcessLimit/2;
    306     }
    307 
    308     private static String buildOomTag(String prefix, String space, int val, int base) {
    309         if (val == base) {
    310             if (space == null) return prefix;
    311             return prefix + "  ";
    312         }
    313         return prefix + "+" + Integer.toString(val-base);
    314     }
    315 
    316     public static String makeOomAdjString(int setAdj) {
    317         if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
    318             return buildOomTag("cch", "  ", setAdj, ProcessList.CACHED_APP_MIN_ADJ);
    319         } else if (setAdj >= ProcessList.SERVICE_B_ADJ) {
    320             return buildOomTag("svcb ", null, setAdj, ProcessList.SERVICE_B_ADJ);
    321         } else if (setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
    322             return buildOomTag("prev ", null, setAdj, ProcessList.PREVIOUS_APP_ADJ);
    323         } else if (setAdj >= ProcessList.HOME_APP_ADJ) {
    324             return buildOomTag("home ", null, setAdj, ProcessList.HOME_APP_ADJ);
    325         } else if (setAdj >= ProcessList.SERVICE_ADJ) {
    326             return buildOomTag("svc  ", null, setAdj, ProcessList.SERVICE_ADJ);
    327         } else if (setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
    328             return buildOomTag("hvy  ", null, setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
    329         } else if (setAdj >= ProcessList.BACKUP_APP_ADJ) {
    330             return buildOomTag("bkup ", null, setAdj, ProcessList.BACKUP_APP_ADJ);
    331         } else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
    332             return buildOomTag("prcp ", null, setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
    333         } else if (setAdj >= ProcessList.VISIBLE_APP_ADJ) {
    334             return buildOomTag("vis  ", null, setAdj, ProcessList.VISIBLE_APP_ADJ);
    335         } else if (setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
    336             return buildOomTag("fore ", null, setAdj, ProcessList.FOREGROUND_APP_ADJ);
    337         } else if (setAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
    338             return buildOomTag("psvc ", null, setAdj, ProcessList.PERSISTENT_SERVICE_ADJ);
    339         } else if (setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
    340             return buildOomTag("pers ", null, setAdj, ProcessList.PERSISTENT_PROC_ADJ);
    341         } else if (setAdj >= ProcessList.SYSTEM_ADJ) {
    342             return buildOomTag("sys  ", null, setAdj, ProcessList.SYSTEM_ADJ);
    343         } else if (setAdj >= ProcessList.NATIVE_ADJ) {
    344             return buildOomTag("ntv  ", null, setAdj, ProcessList.NATIVE_ADJ);
    345         } else {
    346             return Integer.toString(setAdj);
    347         }
    348     }
    349 
    350     public static String makeProcStateString(int curProcState) {
    351         String procState;
    352         switch (curProcState) {
    353             case -1:
    354                 procState = "N ";
    355                 break;
    356             case ActivityManager.PROCESS_STATE_PERSISTENT:
    357                 procState = "P ";
    358                 break;
    359             case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
    360                 procState = "PU";
    361                 break;
    362             case ActivityManager.PROCESS_STATE_TOP:
    363                 procState = "T ";
    364                 break;
    365             case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
    366                 procState = "IF";
    367                 break;
    368             case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
    369                 procState = "IB";
    370                 break;
    371             case ActivityManager.PROCESS_STATE_BACKUP:
    372                 procState = "BU";
    373                 break;
    374             case ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:
    375                 procState = "HW";
    376                 break;
    377             case ActivityManager.PROCESS_STATE_SERVICE:
    378                 procState = "S ";
    379                 break;
    380             case ActivityManager.PROCESS_STATE_RECEIVER:
    381                 procState = "R ";
    382                 break;
    383             case ActivityManager.PROCESS_STATE_HOME:
    384                 procState = "HO";
    385                 break;
    386             case ActivityManager.PROCESS_STATE_LAST_ACTIVITY:
    387                 procState = "LA";
    388                 break;
    389             case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
    390                 procState = "CA";
    391                 break;
    392             case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
    393                 procState = "Ca";
    394                 break;
    395             case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
    396                 procState = "CE";
    397                 break;
    398             default:
    399                 procState = "??";
    400                 break;
    401         }
    402         return procState;
    403     }
    404 
    405     public static void appendRamKb(StringBuilder sb, long ramKb) {
    406         for (int j=0, fact=10; j<6; j++, fact*=10) {
    407             if (ramKb < fact) {
    408                 sb.append(' ');
    409             }
    410         }
    411         sb.append(ramKb);
    412     }
    413 
    414     // The minimum amount of time after a state change it is safe ro collect PSS.
    415     public static final int PSS_MIN_TIME_FROM_STATE_CHANGE = 15*1000;
    416 
    417     // The maximum amount of time we want to go between PSS collections.
    418     public static final int PSS_MAX_INTERVAL = 30*60*1000;
    419 
    420     // The minimum amount of time between successive PSS requests for *all* processes.
    421     public static final int PSS_ALL_INTERVAL = 10*60*1000;
    422 
    423     // The minimum amount of time between successive PSS requests for a process.
    424     private static final int PSS_SHORT_INTERVAL = 2*60*1000;
    425 
    426     // The amount of time until PSS when a process first becomes top.
    427     private static final int PSS_FIRST_TOP_INTERVAL = 10*1000;
    428 
    429     // The amount of time until PSS when a process first goes into the background.
    430     private static final int PSS_FIRST_BACKGROUND_INTERVAL = 20*1000;
    431 
    432     // The amount of time until PSS when a process first becomes cached.
    433     private static final int PSS_FIRST_CACHED_INTERVAL = 30*1000;
    434 
    435     // The amount of time until PSS when an important process stays in the same state.
    436     private static final int PSS_SAME_IMPORTANT_INTERVAL = 15*60*1000;
    437 
    438     // The amount of time until PSS when a service process stays in the same state.
    439     private static final int PSS_SAME_SERVICE_INTERVAL = 20*60*1000;
    440 
    441     // The amount of time until PSS when a cached process stays in the same state.
    442     private static final int PSS_SAME_CACHED_INTERVAL = 30*60*1000;
    443 
    444     public static final int PROC_MEM_PERSISTENT = 0;
    445     public static final int PROC_MEM_TOP = 1;
    446     public static final int PROC_MEM_IMPORTANT = 2;
    447     public static final int PROC_MEM_SERVICE = 3;
    448     public static final int PROC_MEM_CACHED = 4;
    449 
    450     private static final int[] sProcStateToProcMem = new int[] {
    451         PROC_MEM_PERSISTENT,            // ActivityManager.PROCESS_STATE_PERSISTENT
    452         PROC_MEM_PERSISTENT,            // ActivityManager.PROCESS_STATE_PERSISTENT_UI
    453         PROC_MEM_TOP,                   // ActivityManager.PROCESS_STATE_TOP
    454         PROC_MEM_IMPORTANT,             // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
    455         PROC_MEM_IMPORTANT,             // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
    456         PROC_MEM_IMPORTANT,             // ActivityManager.PROCESS_STATE_BACKUP
    457         PROC_MEM_IMPORTANT,             // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
    458         PROC_MEM_SERVICE,               // ActivityManager.PROCESS_STATE_SERVICE
    459         PROC_MEM_CACHED,                // ActivityManager.PROCESS_STATE_RECEIVER
    460         PROC_MEM_CACHED,                // ActivityManager.PROCESS_STATE_HOME
    461         PROC_MEM_CACHED,                // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
    462         PROC_MEM_CACHED,                // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
    463         PROC_MEM_CACHED,                // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
    464         PROC_MEM_CACHED,                // ActivityManager.PROCESS_STATE_CACHED_EMPTY
    465     };
    466 
    467     private static final long[] sFirstAwakePssTimes = new long[] {
    468         PSS_SHORT_INTERVAL,             // ActivityManager.PROCESS_STATE_PERSISTENT
    469         PSS_SHORT_INTERVAL,             // ActivityManager.PROCESS_STATE_PERSISTENT_UI
    470         PSS_FIRST_TOP_INTERVAL,         // ActivityManager.PROCESS_STATE_TOP
    471         PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
    472         PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
    473         PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_BACKUP
    474         PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
    475         PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_SERVICE
    476         PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_RECEIVER
    477         PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_HOME
    478         PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
    479         PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
    480         PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
    481         PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_CACHED_EMPTY
    482     };
    483 
    484     private static final long[] sSameAwakePssTimes = new long[] {
    485         PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_PERSISTENT
    486         PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_PERSISTENT_UI
    487         PSS_SHORT_INTERVAL,             // ActivityManager.PROCESS_STATE_TOP
    488         PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
    489         PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
    490         PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_BACKUP
    491         PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
    492         PSS_SAME_SERVICE_INTERVAL,      // ActivityManager.PROCESS_STATE_SERVICE
    493         PSS_SAME_SERVICE_INTERVAL,      // ActivityManager.PROCESS_STATE_RECEIVER
    494         PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_HOME
    495         PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
    496         PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
    497         PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
    498         PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_EMPTY
    499     };
    500 
    501     public static boolean procStatesDifferForMem(int procState1, int procState2) {
    502         return sProcStateToProcMem[procState1] != sProcStateToProcMem[procState2];
    503     }
    504 
    505     public static long computeNextPssTime(int procState, boolean first, boolean sleeping,
    506             long now) {
    507         final long[] table = sleeping
    508                 ? (first
    509                         ? sFirstAwakePssTimes
    510                         : sSameAwakePssTimes)
    511                 : (first
    512                         ? sFirstAwakePssTimes
    513                         : sSameAwakePssTimes);
    514         return now + table[procState];
    515     }
    516 
    517     long getMemLevel(int adjustment) {
    518         for (int i=0; i<mOomAdj.length; i++) {
    519             if (adjustment <= mOomAdj[i]) {
    520                 return mOomMinFree[i] * 1024;
    521             }
    522         }
    523         return mOomMinFree[mOomAdj.length-1] * 1024;
    524     }
    525 
    526     /**
    527      * Return the maximum pss size in kb that we consider a process acceptable to
    528      * restore from its cached state for running in the background when RAM is low.
    529      */
    530     long getCachedRestoreThresholdKb() {
    531         return mCachedRestoreLevel;
    532     }
    533 
    534     /**
    535      * Set the out-of-memory badness adjustment for a process.
    536      *
    537      * @param pid The process identifier to set.
    538      * @param uid The uid of the app
    539      * @param amt Adjustment value -- lmkd allows -16 to +15.
    540      *
    541      * {@hide}
    542      */
    543     public static final void setOomAdj(int pid, int uid, int amt) {
    544         if (amt == UNKNOWN_ADJ)
    545             return;
    546 
    547         long start = SystemClock.elapsedRealtime();
    548         ByteBuffer buf = ByteBuffer.allocate(4 * 4);
    549         buf.putInt(LMK_PROCPRIO);
    550         buf.putInt(pid);
    551         buf.putInt(uid);
    552         buf.putInt(amt);
    553         writeLmkd(buf);
    554         long now = SystemClock.elapsedRealtime();
    555         if ((now-start) > 250) {
    556             Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
    557                     + " = " + amt);
    558         }
    559     }
    560 
    561     /*
    562      * {@hide}
    563      */
    564     public static final void remove(int pid) {
    565         ByteBuffer buf = ByteBuffer.allocate(4 * 2);
    566         buf.putInt(LMK_PROCREMOVE);
    567         buf.putInt(pid);
    568         writeLmkd(buf);
    569     }
    570 
    571     private static boolean openLmkdSocket() {
    572         try {
    573             sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
    574             sLmkdSocket.connect(
    575                 new LocalSocketAddress("lmkd",
    576                         LocalSocketAddress.Namespace.RESERVED));
    577             sLmkdOutputStream = sLmkdSocket.getOutputStream();
    578         } catch (IOException ex) {
    579             Slog.w(ActivityManagerService.TAG,
    580                    "lowmemorykiller daemon socket open failed");
    581             sLmkdSocket = null;
    582             return false;
    583         }
    584 
    585         return true;
    586     }
    587 
    588     private static void writeLmkd(ByteBuffer buf) {
    589 
    590         for (int i = 0; i < 3; i++) {
    591             if (sLmkdSocket == null) {
    592                     if (openLmkdSocket() == false) {
    593                         try {
    594                             Thread.sleep(1000);
    595                         } catch (InterruptedException ie) {
    596                         }
    597                         continue;
    598                     }
    599             }
    600 
    601             try {
    602                 sLmkdOutputStream.write(buf.array(), 0, buf.position());
    603                 return;
    604             } catch (IOException ex) {
    605                 Slog.w(ActivityManagerService.TAG,
    606                        "Error writing to lowmemorykiller socket");
    607 
    608                 try {
    609                     sLmkdSocket.close();
    610                 } catch (IOException ex2) {
    611                 }
    612 
    613                 sLmkdSocket = null;
    614             }
    615         }
    616     }
    617 }
    618