From 2d314e15c9f0b2efc817b6111d808248a546f48c Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Tue, 4 Apr 2017 16:32:15 -0700 Subject: [PATCH] Set android.display thread to top-app cpusets and schedtune group 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 (cherry picked from commit 474d311cb098e86c078c3f615e1161e2854f1847) --- core/java/android/os/Process.java | 17 ++++++++++++++++- core/jni/android_util_Process.cpp | 17 +++++++++++++++++ .../server/display/DisplayManagerService.java | 11 +++++++++++ .../java/com/android/server/SystemServer.java | 4 ++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 31376587e144f..7a709ed59b15e 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -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 * tid does not exist. * @throws SecurityException Throws SecurityException if your process does @@ -675,6 +675,21 @@ public class Process { public static final native void setThreadGroup(int tid, int group) 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 + * tid 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 diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index a03d3c503e1c3..e8c57716a9b0a 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -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}, diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index ddd918fdcc5d4..d83676b58552f 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -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 diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 63af2da93a86c..f74512a001229 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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));