OSDN Git Service

Set android.display thread to top-app cpusets and schedtune group
authorJoel Fernandes <joelaf@google.com>
Tue, 4 Apr 2017 23:32:15 +0000 (16:32 -0700)
committerJoel Fernandes <joelaf@google.com>
Thu, 6 Apr 2017 03:25:43 +0000 (20:25 -0700)
android.display being in the foreground cpuset group is an issue. As
seen on M/S, during heavily CPU load it is not given core 3 even though
it might be free and causes jank. This patch adds the thread to the
top-app group to ensure it is placed on all cores during scheduling
decisions.

Doing this required a couple of changes:
- new API to set per-thread cpusets
- changes to DisplayManagerService to set the thread to top-app group
- changes to SystemServer to set the policy toward the end, as doing it
  during start of the DisplayManagerService was in issue (issue being
  SystemServer calls setSystemProcess.. -> setProcessGroup which overrides
  the group settings for threads in the system server process, including
  android.display)

Bug: 36631902
Test: Boot and make sure android.display thread is in the top-app group

Change-Id: Icc394ea0ffcf159d11728ad38de114234a29d20f
Signed-off-by: Joel Fernandes <joelaf@google.com>
core/java/android/os/Process.java
core/jni/android_util_Process.cpp
services/core/java/com/android/server/display/DisplayManagerService.java
services/java/com/android/server/SystemServer.java

index 3137658..7a709ed 100644 (file)
@@ -660,7 +660,7 @@ public class Process {
      * @hide
      * @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
@@ -676,6 +676,21 @@ public class Process {
             throws IllegalArgumentException, SecurityException;
 
     /**
+     * Sets the scheduling group and the corresponding cpuset group
+     * @hide
+     * @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.
+     */
+    public static final native void setThreadGroupAndCpuset(int tid, int group)
+            throws IllegalArgumentException, SecurityException;
+
+    /**
      * Sets the scheduling group for a process and all child threads
      * @hide
      * @param pid The identifier of the process to change.
index a03d3c5..e8c5771 100644 (file)
@@ -176,6 +176,22 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint
     }
 }
 
+void android_os_Process_setThreadGroupAndCpuset(JNIEnv* env, jobject clazz, int tid, jint grp)
+{
+    ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
+    SchedPolicy sp = (SchedPolicy) grp;
+    int res = set_sched_policy(tid, sp);
+
+    if (res != NO_ERROR) {
+        signalExceptionForGroupError(env, -res, tid);
+    }
+
+    res = set_cpuset_policy(tid, sp);
+    if (res != NO_ERROR) {
+        signalExceptionForGroupError(env, -res, tid);
+    }
+}
+
 void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
 {
     ALOGV("%s pid=%d grp=%" PRId32, __func__, pid, grp);
@@ -1207,6 +1223,7 @@ static const JNINativeMethod methods[] = {
     {"getThreadPriority",   "(I)I", (void*)android_os_Process_getThreadPriority},
     {"getThreadScheduler",   "(I)I", (void*)android_os_Process_getThreadScheduler},
     {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},
+    {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset},
     {"setProcessGroup",     "(II)V", (void*)android_os_Process_setProcessGroup},
     {"getProcessGroup",     "(I)I", (void*)android_os_Process_getProcessGroup},
     {"getExclusiveCores",   "()[I", (void*)android_os_Process_getExclusiveCores},
index ddd918f..d83676b 100644 (file)
@@ -253,6 +253,17 @@ public final class DisplayManagerService extends SystemService {
 
         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
+
+    }
+
+    public void setupSchedulerPolicies() {
+       /*
+        * android.display is critical to user experience and we should
+        * make sure it is not in the default foregroup groups, add it to
+        * top-app to make sure it uses all the cores and scheduling
+        * settings for top-app when it runs.
+        */
+       Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(), Process.THREAD_GROUP_TOP_APP);
     }
 
     @Override
index 4d5112f..cd2d8f3 100644 (file)
@@ -614,6 +614,10 @@ public final class SystemServer {
         mActivityManagerService.setSystemProcess();
         traceEnd();
 
+        // DisplayManagerService needs to setup android.display scheduling related policies
+        // since setSystemProcess() would have overridden policies due to setProcessGroup
+        mDisplayManagerService.setupSchedulerPolicies();
+
         // Manages Overlay packages
         traceBeginAndSlog("StartOverlayManagerService");
         mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));