Scheduling group cleanup

The C++ API for scheduling groups is going away, so use the C API.

Renumber THREAD_GROUP_* constants to have the same values as SP_*.
They are @hide so this should be OK.

The old THREAD_GROUP_FG_BOOST constant is removed, and replaced by a
(private) THREAD_GROUP_FOREGROUND constant that is just a placeholder
to correspond to SP_FOREGROUND.  It is not usable at this level.

Improved performance of android_os_Process_setProcessGroup:
avoid unnecessary syscall to getpriority for each tid.

Fixed error handling in android_os_Process_setThreadGroup.
It raises an exception if set_sched_policy() returns an error.

Add comments and fix typos in existing comments.

Change-Id: Ib922e92c945985c695ef0addbd2b83b8e82865f8
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 770bf1c..8e041bb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -266,25 +266,38 @@
      */
     public static final int SCHED_IDLE = 5;
 
-    /**
-     * Default thread group - gets a 'normal' share of the CPU
-     * @hide
-     */
-    public static final int THREAD_GROUP_DEFAULT = 0;
+    // Keep in sync with SP_* constants of enum type SchedPolicy
+    // declared in system/core/include/cutils/sched_policy.h,
+    // except THREAD_GROUP_DEFAULT does not correspond to any SP_* value.
 
     /**
-     * Background non-interactive thread group - All threads in
+     * Default thread group -
+     * has meaning with setProcessGroup() only, cannot be used with setThreadGroup().
+     * When used with setProcessGroup(), the group of each thread in the process
+     * is conditionally changed based on that thread's current priority, as follows:
+     * threads with priority numerically less than THREAD_PRIORITY_BACKGROUND
+     * are moved to foreground thread group.  All other threads are left unchanged.
+     * @hide
+     */
+    public static final int THREAD_GROUP_DEFAULT = -1;
+
+    /**
+     * Background thread group - All threads in
      * this group are scheduled with a reduced share of the CPU.
+     * Value is same as constant SP_BACKGROUND of enum SchedPolicy.
+     * FIXME rename to THREAD_GROUP_BACKGROUND.
      * @hide
      */
-    public static final int THREAD_GROUP_BG_NONINTERACTIVE = 1;
+    public static final int THREAD_GROUP_BG_NONINTERACTIVE = 0;
 
     /**
-     * Foreground 'boost' thread group - All threads in
-     * this group are scheduled with an increased share of the CPU
+     * Foreground thread group - All threads in
+     * this group are scheduled with a normal share of the CPU.
+     * Value is same as constant SP_FOREGROUND of enum SchedPolicy.
+     * Not used at this level.
      * @hide
      **/
-    public static final int THREAD_GROUP_FG_BOOST = 2;
+    private static final int THREAD_GROUP_FOREGROUND = 1;
 
     public static final int SIGNAL_QUIT = 3;
     public static final int SIGNAL_KILL = 9;
@@ -672,28 +685,37 @@
     /**
      * Sets the scheduling group for a thread.
      * @hide
-     * @param tid The indentifier of the thread/process to change.
-     * @param group The target group for this thread/process.
+     * @param tid The identifier of the thread to change.
+     * @param group The target group for this thread from THREAD_GROUP_*.
      * 
      * @throws IllegalArgumentException Throws IllegalArgumentException if
      * <var>tid</var> does not exist.
      * @throws SecurityException Throws SecurityException if your process does
      * not have permission to modify the given thread, or to use the given
      * priority.
+     * If the thread is a thread group leader, that is it's gettid() == getpid(),
+     * then the other threads in the same thread group are _not_ affected.
      */
     public static final native void setThreadGroup(int tid, int group)
             throws IllegalArgumentException, SecurityException;
+
     /**
      * Sets the scheduling group for a process and all child threads
      * @hide
-     * @param pid The indentifier of the process to change.
-     * @param group The target group for this process.
+     * @param pid The identifier of the process to change.
+     * @param group The target group for this process from THREAD_GROUP_*.
      * 
      * @throws IllegalArgumentException Throws IllegalArgumentException if
      * <var>tid</var> does not exist.
      * @throws SecurityException Throws SecurityException if your process does
      * not have permission to modify the given thread, or to use the given
      * priority.
+     *
+     * group == THREAD_GROUP_DEFAULT means to move all non-background priority
+     * threads to the foreground scheduling group, but to leave background
+     * priority threads alone.  group == THREAD_GROUP_BG_NONINTERACTIVE moves all
+     * threads, regardless of priority, to the background scheduling group.
+     * group == THREAD_GROUP_FOREGROUND is not allowed.
      */
     public static final native void setProcessGroup(int pid, int group)
             throws IllegalArgumentException, SecurityException;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 41cc203..93be342a 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -21,6 +21,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <cutils/sched_policy.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
@@ -49,6 +50,8 @@
 static pthread_key_t gBgKey = -1;
 #endif
 
+// For both of these, err should be in the errno range (positive), not a status_t (negative)
+
 static void signalExceptionForPriorityError(JNIEnv* env, int err)
 {
     switch (err) {
@@ -168,27 +171,36 @@
     return -1;
 }
 
-void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
+void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp)
 {
-    int res = androidSetThreadSchedulingGroup(pid, grp);
+    ALOGV("%s tid=%d grp=%d", __func__, tid, grp);
+    SchedPolicy sp = (SchedPolicy) grp;
+    int res = set_sched_policy(tid, sp);
     if (res != NO_ERROR) {
-        signalExceptionForGroupError(env, res == BAD_VALUE ? EINVAL : errno);
-        return;
+        signalExceptionForGroupError(env, -res);
     }
 }
 
 void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
 {
+    ALOGV("%s pid=%d grp=%d", __func__, pid, grp);
     DIR *d;
     FILE *fp;
     char proc_path[255];
     struct dirent *de;
 
-    if (grp > ANDROID_TGROUP_MAX || grp < 0) {
+    if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) {
         signalExceptionForGroupError(env, EINVAL);
         return;
     }
 
+    bool isDefault = false;
+    if (grp < 0) {
+        grp = SP_FOREGROUND;
+        isDefault = true;
+    }
+    SchedPolicy sp = (SchedPolicy) grp;
+
 #if POLICY_DEBUG
     char cmdline[32];
     int fd;
@@ -203,7 +215,7 @@
         close(fd);
     }
 
-    if (grp == ANDROID_TGROUP_BG_NONINTERACT) {
+    if (sp == SP_BACKGROUND) {
         ALOGD("setProcessGroup: vvv pid %d (%s)", pid, cmdline);
     } else {
         ALOGD("setProcessGroup: ^^^ pid %d (%s)", pid, cmdline);
@@ -230,16 +242,18 @@
             continue;
         }
 
-        t_pri = getpriority(PRIO_PROCESS, t_pid);
+        if (isDefault) {
+            t_pri = getpriority(PRIO_PROCESS, t_pid);
 
-        if (grp == ANDROID_TGROUP_DEFAULT &&
-            t_pri >= ANDROID_PRIORITY_BACKGROUND) {
-            // This task wants to stay at background
-            continue;
+            if (t_pri >= ANDROID_PRIORITY_BACKGROUND) {
+                // This task wants to stay at background
+                continue;
+            }
         }
 
-        if (androidSetThreadSchedulingGroup(t_pid, grp) != NO_ERROR) {
-            signalExceptionForGroupError(env, errno);
+        int err = set_sched_policy(t_pid, sp);
+        if (err != NO_ERROR) {
+            signalExceptionForGroupError(env, -err);
             break;
         }
     }