am 91ecb36d: ActivityManagerService use lmkd low memory killer daemon -- DO NOT MERGE

* commit '91ecb36df50be3446809e9da2a8f571d157f7549':
  ActivityManagerService use lmkd low memory killer daemon -- DO NOT MERGE
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 631edd6..057f516 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -892,19 +892,6 @@
     }
 
     /**
-     * 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 601975a..cbed99f 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -344,23 +344,6 @@
     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 @@
     {"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 4540c1c..3906745 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 @@
      */
     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 @@
             boolean restarting, boolean allowRestart, int index) {
         if (index >= 0) {
             removeLruProcessLocked(app);
+            ProcessList.remove(app.pid);
         }
 
         mProcessesToGc.remove(app);
@@ -15181,16 +15186,13 @@
         }
 
         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 d3777c7..f5920c8 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 @@
 
 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 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 @@
     // 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 @@
     };
     // 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 @@
 
     private boolean mHaveDisplaySize;
 
+    private static LocalSocket sLmkdSocket;
+    private static OutputStream sLmkdOutputStream;
+
     ProcessList() {
         MemInfoReader minfo = new MemInfoReader();
         minfo.readMemInfo();
@@ -202,9 +219,6 @@
                     + " 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 @@
         }
 
         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 @@
         // 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 @@
             }
         }
 
-        //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 @@
         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;
             }
         }
     }