diff options
| -rw-r--r-- | core/java/android/os/Process.java | 13 | ||||
| -rw-r--r-- | core/jni/android_util_Process.cpp | 18 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessList.java | 135 | 
4 files changed, 113 insertions, 73 deletions
| diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 631edd67957b..057f516af17b 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -892,19 +892,6 @@ public class Process {      }      /** -     * Set the out-of-memory badness adjustment for a process. -     *  -     * @param pid The process identifier to set. -     * @param amt Adjustment value -- linux allows -16 to +15. -     *  -     * @return Returns true if the underlying system supports this -     *         feature, else false. -     *          -     * {@hide} -     */ -    public static final native boolean setOomAdj(int pid, int amt); - -    /**       * Adjust the swappiness level for a process.       *       * @param pid The process identifier to set. diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 601975af01b9..cbed99f9acad 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -344,23 +344,6 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz,      return pri;  } -jboolean android_os_Process_setOomAdj(JNIEnv* env, jobject clazz, -                                      jint pid, jint adj) -{ -#ifdef HAVE_OOM_ADJ -    char text[64]; -    sprintf(text, "/proc/%d/oom_adj", pid); -    int fd = open(text, O_WRONLY); -    if (fd >= 0) { -        sprintf(text, "%d", adj); -        write(fd, text, strlen(text)); -        close(fd); -    } -    return true; -#endif -    return false; -} -  jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz,                                            jint pid, jboolean is_increased)  { @@ -1023,7 +1006,6 @@ static const JNINativeMethod methods[] = {      {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},      {"setProcessGroup",     "(II)V", (void*)android_os_Process_setProcessGroup},      {"getProcessGroup",     "(I)I", (void*)android_os_Process_getProcessGroup}, -    {"setOomAdj",   "(II)Z", (void*)android_os_Process_setOomAdj},      {"setSwappiness",   "(IZ)Z", (void*)android_os_Process_setSwappiness},      {"setArgV0",    "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},      {"setUid", "(I)I", (void*)android_os_Process_setUid}, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4540c1cbbe6b..39067459d08a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3592,9 +3592,13 @@ public final class ActivityManagerService extends ActivityManagerNative       */      private final void handleAppDiedLocked(ProcessRecord app,              boolean restarting, boolean allowRestart) { +        int pid = app.pid;          cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);          if (!restarting) {              removeLruProcessLocked(app); +            if (pid > 0) { +                ProcessList.remove(pid); +            }          }          if (mProfileProc == app) { @@ -12319,6 +12323,7 @@ public final class ActivityManagerService extends ActivityManagerNative              boolean restarting, boolean allowRestart, int index) {          if (index >= 0) {              removeLruProcessLocked(app); +            ProcessList.remove(app.pid);          }          mProcessesToGc.remove(app); @@ -15181,16 +15186,13 @@ public final class ActivityManagerService extends ActivityManagerNative          }          if (app.curAdj != app.setAdj) { -            if (Process.setOomAdj(app.pid, app.curAdj)) { -                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v( -                    TAG, "Set " + app.pid + " " + app.processName + -                    " adj " + app.curAdj + ": " + app.adjType); -                app.setAdj = app.curAdj; -            } else { -                success = false; -                Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj); -            } +            ProcessList.setOomAdj(app.pid, app.curAdj); +            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v( +                TAG, "Set " + app.pid + " " + app.processName + +                " adj " + app.curAdj + ": " + app.adjType); +            app.setAdj = app.curAdj;          } +          if (app.setSchedGroup != app.curSchedGroup) {              app.setSchedGroup = app.curSchedGroup;              if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG, diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index d3777c7ae134..f5920c8db355 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -18,6 +18,8 @@ package com.android.server.am;  import java.io.FileOutputStream;  import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer;  import android.app.ActivityManager;  import com.android.internal.util.MemInfoReader; @@ -26,6 +28,8 @@ import com.android.server.wm.WindowManagerService;  import android.content.res.Resources;  import android.graphics.Point;  import android.os.SystemProperties; +import android.net.LocalSocketAddress; +import android.net.LocalSocket;  import android.util.Slog;  import android.view.Display; @@ -141,6 +145,16 @@ final class ProcessList {      // Threshold of number of cached+empty where we consider memory critical.      static final int TRIM_LOW_THRESHOLD = 5; +    // Low Memory Killer Daemon command codes. +    // These must be kept in sync with the definitions in lmkd.c +    // +    // LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs) +    // LMK_PROCPRIO <pid> <prio> +    // LMK_PROCREMOVE <pid> +    static final byte LMK_TARGET = 0; +    static final byte LMK_PROCPRIO = 1; +    static final byte LMK_PROCREMOVE = 2; +      // These are the various interesting memory levels that we will give to      // the OOM killer.  Note that the OOM killer only supports 6 slots, so we      // can't give it a different value for every possible kind of process. @@ -150,18 +164,18 @@ final class ProcessList {      };      // These are the low-end OOM level limits.  This is appropriate for an      // HVGA or smaller phone with less than 512MB.  Values are in KB. -    private final long[] mOomMinFreeLow = new long[] { +    private final int[] mOomMinFreeLow = new int[] {              8192, 12288, 16384,              24576, 28672, 32768      };      // These are the high-end OOM level limits.  This is appropriate for a      // 1280x800 or larger screen with around 1GB RAM.  Values are in KB. -    private final long[] mOomMinFreeHigh = new long[] { +    private final int[] mOomMinFreeHigh = new int[] {              49152, 61440, 73728,              86016, 98304, 122880      };      // The actual OOM killer memory levels we are using. -    private final long[] mOomMinFree = new long[mOomAdj.length]; +    private final int[] mOomMinFree = new int[mOomAdj.length];      private final long mTotalMemMb; @@ -169,6 +183,9 @@ final class ProcessList {      private boolean mHaveDisplaySize; +    private static LocalSocket sLmkdSocket; +    private static OutputStream sLmkdOutputStream; +      ProcessList() {          MemInfoReader minfo = new MemInfoReader();          minfo.readMemInfo(); @@ -202,9 +219,6 @@ final class ProcessList {                      + " dh=" + displayHeight);          } -        StringBuilder adjString = new StringBuilder(); -        StringBuilder memString = new StringBuilder(); -          float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;          if (scale < 0) scale = 0;          else if (scale > 1) scale = 1; @@ -217,20 +231,20 @@ final class ProcessList {          }          for (int i=0; i<mOomAdj.length; i++) { -            long low = mOomMinFreeLow[i]; -            long high = mOomMinFreeHigh[i]; -            mOomMinFree[i] = (long)(low + ((high-low)*scale)); +            int low = mOomMinFreeLow[i]; +            int high = mOomMinFreeHigh[i]; +            mOomMinFree[i] = (int)(low + ((high-low)*scale));          }          if (minfree_abs >= 0) {              for (int i=0; i<mOomAdj.length; i++) { -                mOomMinFree[i] = (long)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); +                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] += (long)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]); +                mOomMinFree[i] += (int)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);                  if (mOomMinFree[i] < 0) {                      mOomMinFree[i] = 0;                  } @@ -242,15 +256,6 @@ final class ProcessList {          // before killing background processes.          mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024) / 3; -        for (int i=0; i<mOomAdj.length; i++) { -            if (i > 0) { -                adjString.append(','); -                memString.append(','); -            } -            adjString.append(mOomAdj[i]); -            memString.append((mOomMinFree[i]*1024)/PAGE_SIZE); -        } -          // 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; @@ -268,10 +273,15 @@ final class ProcessList {              }          } -        //Slog.i("XXXXXXX", "******************************* MINFREE: " + memString);          if (write) { -            writeFile("/sys/module/lowmemorykiller/parameters/adj", adjString.toString()); -            writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString()); +            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 @@ -506,19 +516,78 @@ final class ProcessList {          return mCachedRestoreLevel;      } -    private void writeFile(String path, String data) { -        FileOutputStream fos = null; +    /** +     * Set the out-of-memory badness adjustment for a process. +     * +     * @param pid The process identifier to set. +     * @param amt Adjustment value -- lmkd allows -16 to +15. +     * +     * {@hide} +     */ +    public static final void setOomAdj(int pid, int amt) { +        if (amt == UNKNOWN_ADJ) +            return; + +        ByteBuffer buf = ByteBuffer.allocate(4 * 3); +        buf.putInt(LMK_PROCPRIO); +        buf.putInt(pid); +        buf.putInt(amt); +        writeLmkd(buf); +    } + +    /* +     * {@hide} +     */ +    public static final void remove(int pid) { +        ByteBuffer buf = ByteBuffer.allocate(4 * 2); +        buf.putInt(LMK_PROCREMOVE); +        buf.putInt(pid); +        writeLmkd(buf); +    } + +    private static boolean openLmkdSocket() {          try { -            fos = new FileOutputStream(path); -            fos.write(data.getBytes()); -        } catch (IOException e) { -            Slog.w(ActivityManagerService.TAG, "Unable to write " + path); -        } finally { -            if (fos != null) { +            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; +    } + +    private static void writeLmkd(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 { -                    fos.close(); -                } catch (IOException e) { +                    sLmkdSocket.close(); +                } catch (IOException ex2) {                  } + +                sLmkdSocket = null;              }          }      } |