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 <joelaf@google.com>
(cherry picked from commit 474d311cb098e86c078c3f615e1161e2854f1847)
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 3137658..7a709ed 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -660,7 +660,7 @@
* @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 @@
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.
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index a03d3c5..e8c5771 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -176,6 +176,22 @@
}
}
+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 @@
{"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 ddd918f..d83676b 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 @@
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 63af2da..f74512a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -614,6 +614,10 @@
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));