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