Process: Add support for using scheduler policies instead of cgroups.
Preference is given to cgroups if available.

Signed-off-by: San Mehat <san@google.com>
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 723fd4b..7748aba 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -50,14 +50,6 @@
 #undef __KERNEL__
 #endif
 
-/*
- * List of cgroup names which map to ANDROID_TGROUP_ values in Thread.h
- * and Process.java
- * These names are used to construct the path to the cgroup control dir
- */
-
-static const char *cgroup_names[] = { NULL, "bg_non_interactive", "fg_boost" };
-
 using namespace android;
 
 static void signalExceptionForPriorityError(JNIEnv* env, jobject obj, int err)
@@ -194,14 +186,13 @@
     return -1;
 }
 
-static int add_pid_to_cgroup(int pid, int grp)
+static int add_pid_to_cgroup(int pid, const char *grp_name)
 {
     int fd;
     char path[255];
     char text[64];
 
-    sprintf(path, "/dev/cpuctl/%s/tasks",
-           (cgroup_names[grp] ? cgroup_names[grp] : ""));
+    sprintf(path, "/dev/cpuctl/%s/tasks", grp_name);
 
     if ((fd = open(path, O_WRONLY)) < 0)
         return -1;
@@ -216,6 +207,37 @@
     return 0;
 }
 
+void setSchedPolicy(JNIEnv* env, jobject clazz, int pid, SchedPolicy policy)
+{
+    static int __sys_supports_schedgroups = -1;
+
+    if (__sys_supports_schedgroups < 0) {
+        if (!access("/dev/cpuctl/tasks", F_OK)) {
+            __sys_supports_schedgroups = 1;
+        } else {
+            __sys_supports_schedgroups = 0;
+        }
+    }
+
+    if (__sys_supports_schedgroups) {
+        const char *grp = NULL;
+
+        if (policy == SP_BACKGROUND) {
+            grp = "bg_non_interactive";
+        }
+
+        if (add_pid_to_cgroup(pid, grp)) {
+            if (errno != ESRCH && errno != ENOENT)
+                signalExceptionForGroupError(env, clazz, errno);
+        }
+    } else {
+        struct sched_param param;
+
+        param.sched_priority = 0;
+        sched_setscheduler(pid, (policy == SP_BACKGROUND) ? 5 : 0, &param);
+    }
+}
+
 void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
 {
     if (grp > ANDROID_TGROUP_MAX || grp < 0) { 
@@ -223,11 +245,9 @@
         return;
     }
 
-    if (add_pid_to_cgroup(pid, grp)) {
-        // If the thread exited on us, don't generate an exception
-        if (errno != ESRCH && errno != ENOENT)
-            signalExceptionForGroupError(env, clazz, errno);
-    }
+    setSchedPolicy(env, clazz, pid,
+                   (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
+                           SP_BACKGROUND : SP_FOREGROUND);
 }
 
 void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp) 
@@ -271,14 +291,9 @@
             continue;
         }
      
-        if (add_pid_to_cgroup(t_pid, grp)) {
-            // If the thread exited on us, ignore it and keep going
-            if (errno != ESRCH && errno != ENOENT) {
-                signalExceptionForGroupError(env, clazz, errno);
-                closedir(d);
-                return;
-            }
-        }
+        setSchedPolicy(env, clazz, t_pid,
+                       (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
+                               SP_BACKGROUND : SP_FOREGROUND);
     }
     closedir(d);
 }
@@ -287,9 +302,9 @@
                                               jint pid, jint pri)
 {
     if (pri >= ANDROID_PRIORITY_BACKGROUND) {
-        add_pid_to_cgroup(pid, ANDROID_TGROUP_BG_NONINTERACT);
+        setSchedPolicy(env, clazz, pid, SP_BACKGROUND);
     } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
-        add_pid_to_cgroup(pid, ANDROID_TGROUP_DEFAULT);
+        setSchedPolicy(env, clazz, pid, SP_FOREGROUND);
     }
 
     if (setpriority(PRIO_PROCESS, pid, pri) < 0) {
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 0fc533f..f5304f7 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -90,6 +90,11 @@
     ANDROID_TGROUP_MAX              = ANDROID_TGROUP_FG_BOOST,
 };
 
+typedef enum {
+    SP_BACKGROUND = 0,
+    SP_FOREGROUND = 1,
+} SchedPolicy;
+
 // Create and run a new thread.
 extern int androidCreateThread(android_thread_func_t, void *);