ProcessList.java revision 59c009776dae5ccbdfb93d7151ff2065ca049dc3
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.FileOutputStream;
20import java.io.IOException;
21
22import com.android.internal.util.MemInfoReader;
23import com.android.server.wm.WindowManagerService;
24
25import android.graphics.Point;
26import android.util.Slog;
27import android.view.Display;
28
29/**
30 * Activity manager code dealing with processes.
31 */
32class ProcessList {
33    // The minimum time we allow between crashes, for us to consider this
34    // application to be bad and stop and its services and reject broadcasts.
35    static final int MIN_CRASH_INTERVAL = 60*1000;
36
37    // OOM adjustments for processes in various states:
38
39    // This is a process only hosting activities that are not visible,
40    // so it can be killed without any disruption.
41    static final int HIDDEN_APP_MAX_ADJ = 15;
42    static int HIDDEN_APP_MIN_ADJ = 9;
43
44    // The B list of SERVICE_ADJ -- these are the old and decrepit
45    // services that aren't as shiny and interesting as the ones in the A list.
46    static final int SERVICE_B_ADJ = 8;
47
48    // This is the process of the previous application that the user was in.
49    // This process is kept above other things, because it is very common to
50    // switch back to the previous app.  This is important both for recent
51    // task switch (toggling between the two top recent apps) as well as normal
52    // UI flow such as clicking on a URI in the e-mail app to view in the browser,
53    // and then pressing back to return to e-mail.
54    static final int PREVIOUS_APP_ADJ = 7;
55
56    // This is a process holding the home application -- we want to try
57    // avoiding killing it, even if it would normally be in the background,
58    // because the user interacts with it so much.
59    static final int HOME_APP_ADJ = 6;
60
61    // This is a process holding an application service -- killing it will not
62    // have much of an impact as far as the user is concerned.
63    static final int SERVICE_ADJ = 5;
64
65    // This is a process currently hosting a backup operation.  Killing it
66    // is not entirely fatal but is generally a bad idea.
67    static final int BACKUP_APP_ADJ = 4;
68
69    // This is a process with a heavy-weight application.  It is in the
70    // background, but we want to try to avoid killing it.  Value set in
71    // system/rootdir/init.rc on startup.
72    static final int HEAVY_WEIGHT_APP_ADJ = 3;
73
74    // This is a process only hosting components that are perceptible to the
75    // user, and we really want to avoid killing them, but they are not
76    // immediately visible. An example is background music playback.
77    static final int PERCEPTIBLE_APP_ADJ = 2;
78
79    // This is a process only hosting activities that are visible to the
80    // user, so we'd prefer they don't disappear.
81    static final int VISIBLE_APP_ADJ = 1;
82
83    // This is the process running the current foreground app.  We'd really
84    // rather not kill it!
85    static final int FOREGROUND_APP_ADJ = 0;
86
87    // This is a system persistent process, such as telephony.  Definitely
88    // don't want to kill it, but doing so is not completely fatal.
89    static final int PERSISTENT_PROC_ADJ = -12;
90
91    // The system process runs at the default adjustment.
92    static final int SYSTEM_ADJ = -16;
93
94    // Memory pages are 4K.
95    static final int PAGE_SIZE = 4*1024;
96
97    // The minimum number of hidden apps we want to be able to keep around,
98    // without empty apps being able to push them out of memory.
99    static final int MIN_HIDDEN_APPS = 2;
100
101    // The maximum number of hidden processes we will keep around before
102    // killing them; this is just a control to not let us go too crazy with
103    // keeping around processes on devices with large amounts of RAM.
104    static final int MAX_HIDDEN_APPS = 15;
105
106    // We put empty content processes after any hidden processes that have
107    // been idle for less than 15 seconds.
108    static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
109
110    // We put empty content processes after any hidden processes that have
111    // been idle for less than 120 seconds.
112    static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
113
114    // These are the various interesting memory levels that we will give to
115    // the OOM killer.  Note that the OOM killer only supports 6 slots, so we
116    // can't give it a different value for every possible kind of process.
117    private final int[] mOomAdj = new int[] {
118            FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
119            BACKUP_APP_ADJ, HIDDEN_APP_MIN_ADJ, HIDDEN_APP_MAX_ADJ
120    };
121    // These are the low-end OOM level limits.  This is appropriate for an
122    // HVGA or smaller phone with less than 512MB.  Values are in KB.
123    private final long[] mOomMinFreeLow = new long[] {
124            8192, 12288, 16384,
125            24576, 28672, 32768
126    };
127    // These are the high-end OOM level limits.  This is appropriate for a
128    // 1280x800 or larger screen with around 1GB RAM.  Values are in KB.
129    private final long[] mOomMinFreeHigh = new long[] {
130            32768, 40960, 49152,
131            57344, 65536, 81920
132    };
133    // The actual OOM killer memory levels we are using.
134    private final long[] mOomMinFree = new long[mOomAdj.length];
135
136    private final long mTotalMemMb;
137
138    private boolean mHaveDisplaySize;
139
140    ProcessList() {
141        MemInfoReader minfo = new MemInfoReader();
142        minfo.readMemInfo();
143        mTotalMemMb = minfo.getTotalSize()/(1024*1024);
144        updateOomLevels(0, 0, false);
145    }
146
147    void applyDisplaySize(WindowManagerService wm) {
148        if (!mHaveDisplaySize) {
149            Point p = new Point();
150            wm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, p);
151            if (p.x != 0 && p.y != 0) {
152                updateOomLevels(p.x, p.y, true);
153                mHaveDisplaySize = true;
154            }
155        }
156    }
157
158    private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
159        // Scale buckets from avail memory: at 300MB we use the lowest values to
160        // 700MB or more for the top values.
161        float scaleMem = ((float)(mTotalMemMb-300))/(700-300);
162
163        // Scale buckets from screen size.
164        int minSize = 320*480;  //  153600
165        int maxSize = 1280*800; // 1024000  230400 870400  .264
166        float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
167        //Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight);
168
169        StringBuilder adjString = new StringBuilder();
170        StringBuilder memString = new StringBuilder();
171
172        float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;
173        if (scale < 0) scale = 0;
174        else if (scale > 1) scale = 1;
175        for (int i=0; i<mOomAdj.length; i++) {
176            long low = mOomMinFreeLow[i];
177            long high = mOomMinFreeHigh[i];
178            mOomMinFree[i] = (long)(low + ((high-low)*scale));
179
180            if (i > 0) {
181                adjString.append(',');
182                memString.append(',');
183            }
184            adjString.append(mOomAdj[i]);
185            memString.append((mOomMinFree[i]*1024)/PAGE_SIZE);
186        }
187
188        //Slog.i("XXXXXXX", "******************************* MINFREE: " + memString);
189        if (write) {
190            writeFile("/sys/module/lowmemorykiller/parameters/adj", adjString.toString());
191            writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString());
192        }
193        // GB: 2048,3072,4096,6144,7168,8192
194        // HC: 8192,10240,12288,14336,16384,20480
195    }
196
197    long getMemLevel(int adjustment) {
198        for (int i=0; i<mOomAdj.length; i++) {
199            if (adjustment <= mOomAdj[i]) {
200                return mOomMinFree[i] * 1024;
201            }
202        }
203        return mOomMinFree[mOomAdj.length-1] * 1024;
204    }
205
206    private void writeFile(String path, String data) {
207        FileOutputStream fos = null;
208        try {
209            fos = new FileOutputStream(path);
210            fos.write(data.getBytes());
211        } catch (IOException e) {
212            Slog.w(ActivityManagerService.TAG, "Unable to write " + path);
213        } finally {
214            if (fos != null) {
215                try {
216                    fos.close();
217                } catch (IOException e) {
218                }
219            }
220        }
221    }
222}
223