Activity Manager changes the scheduling group of processes.

The algorithm for this is currently very simple: all persistent processes are
always in the normal scheduling group, all other processes are normal if their
oom_adj is as good or better than VISIBLE, otherwise they are in the background
group.

Note that this currently results in a fair number of log messages about not
being able to change the group, since the system process does not have
permission to do so.  Once a kernel fix is in, these will go away and the code
will start working.
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f2959e3..d1c40b4 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4733,6 +4733,7 @@
         
         app.thread = thread;
         app.curAdj = app.setAdj = -100;
+        app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
         app.forcingToForeground = null;
         app.foregroundServices = false;
         app.debugging = false;
@@ -8802,9 +8803,9 @@
                       + " #" + i + ":");
                 r.dump(pw, prefix + "  ");
             } else if (inclOomAdj) {
-                pw.println(String.format("%s%s #%2d: oom_adj=%3d %s",
+                pw.println(String.format("%s%s #%2d: adj=%3d/%d %s",
                         prefix, (r.persistent ? persistentLabel : normalLabel),
-                        i, r.setAdj, r.toString()));
+                        i, r.setAdj, r.setSchedGroup, r.toString()));
             } else {
                 pw.println(String.format("%s%s #%2d: %s",
                         prefix, (r.persistent ? persistentLabel : normalLabel),
@@ -11830,7 +11831,10 @@
         }
 
         app.curAdj = adj;
-
+        app.curSchedGroup = (adj > VISIBLE_APP_ADJ && !app.persistent)
+                ? Process.THREAD_GROUP_BG_NONINTERACTIVE
+                : Process.THREAD_GROUP_DEFAULT;
+        
         return adj;
     }
 
@@ -11975,6 +11979,28 @@
                     return false;
                 }
             }
+            if (app.setSchedGroup != app.curSchedGroup) {
+                app.setSchedGroup = app.curSchedGroup;
+                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG,
+                        "Setting process group of " + app.processName
+                        + " to " + app.curSchedGroup);
+                if (true) {
+                    try {
+                        Process.setProcessGroup(app.pid, app.curSchedGroup);
+                    } catch (Exception e) {
+                        Log.w(TAG, "Failed setting process group of " + app.pid
+                                + " to " + app.curSchedGroup);
+                    }
+                }
+                if (false) {
+                    if (app.thread != null) {
+                        try {
+                            app.thread.setSchedulingGroup(app.curSchedGroup);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                }
+            }
         }
 
         return true;