Add ability to guard a thread against setting its own prio to bg
The guard is compiled out by default because it adds overhead to android.os.Process.setPriority(). Change-Id: Ibb2a648c6349b381abb7ae62a358888b04fba871
This commit is contained in:
@ -625,6 +625,15 @@ public class Process {
|
||||
public static final native void setThreadPriority(int tid, int priority)
|
||||
throws IllegalArgumentException, SecurityException;
|
||||
|
||||
/**
|
||||
* Call with 'false' to cause future calls to {@link #setThreadPriority(int)} to
|
||||
* throw an exception if passed a background-level thread priority. This is only
|
||||
* effective if the JNI layer is built with GUARD_THREAD_PRIORITY defined to 1.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final native void setCanSelfBackground(boolean backgroundOk);
|
||||
|
||||
/**
|
||||
* Sets the scheduling group for a thread.
|
||||
* @hide
|
||||
|
@ -52,9 +52,15 @@ pid_t gettid() { return syscall(__NR_gettid);}
|
||||
#endif
|
||||
|
||||
#define POLICY_DEBUG 0
|
||||
#define GUARD_THREAD_PRIORITY 0
|
||||
|
||||
using namespace android;
|
||||
|
||||
#if GUARD_THREAD_PRIORITY
|
||||
Mutex gKeyCreateMutex;
|
||||
static pthread_key_t gBgKey = -1;
|
||||
#endif
|
||||
|
||||
static void signalExceptionForPriorityError(JNIEnv* env, jobject obj, int err)
|
||||
{
|
||||
switch (err) {
|
||||
@ -264,9 +270,41 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, jboolean bgOk) {
|
||||
// Establishes the calling thread as illegal to put into the background.
|
||||
// Typically used only for the system process's main looper.
|
||||
#if GUARD_THREAD_PRIORITY
|
||||
LOGV("Process.setCanSelfBackground(%d) : tid=%d", bgOk, androidGetTid());
|
||||
{
|
||||
Mutex::Autolock _l(gKeyCreateMutex);
|
||||
if (gBgKey == -1) {
|
||||
pthread_key_create(&gBgKey, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// inverted: not-okay, we set a sentinel value
|
||||
pthread_setspecific(gBgKey, (void*)(bgOk ? 0 : 0xbaad));
|
||||
#endif
|
||||
}
|
||||
|
||||
void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
|
||||
jint pid, jint pri)
|
||||
{
|
||||
#if GUARD_THREAD_PRIORITY
|
||||
// if we're putting the current thread into the background, check the TLS
|
||||
// to make sure this thread isn't guarded. If it is, raise an exception.
|
||||
if (pri >= ANDROID_PRIORITY_BACKGROUND) {
|
||||
if (pid == androidGetTid()) {
|
||||
void* bgOk = pthread_getspecific(gBgKey);
|
||||
if (bgOk == ((void*)0xbaad)) {
|
||||
LOGE("Thread marked fg-only put self in background!");
|
||||
jniThrowException(env, "java/lang/SecurityException", "May not put this thread into background");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int rc = androidSetThreadPriority(pid, pri);
|
||||
if (rc != 0) {
|
||||
if (rc == INVALID_OPERATION) {
|
||||
@ -852,6 +890,7 @@ static const JNINativeMethod methods[] = {
|
||||
{"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName},
|
||||
{"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName},
|
||||
{"setThreadPriority", "(II)V", (void*)android_os_Process_setThreadPriority},
|
||||
{"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
|
||||
{"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority},
|
||||
{"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority},
|
||||
{"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
|
||||
|
@ -80,6 +80,7 @@ class ServerThread extends Thread {
|
||||
android.os.Process.THREAD_PRIORITY_FOREGROUND);
|
||||
|
||||
BinderInternal.disableBackgroundScheduling(true);
|
||||
android.os.Process.setCanSelfBackground(false);
|
||||
|
||||
String factoryTestStr = SystemProperties.get("ro.factorytest");
|
||||
int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
|
||||
|
@ -572,6 +572,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
mHaveInputMethods);
|
||||
android.os.Process.setThreadPriority(
|
||||
android.os.Process.THREAD_PRIORITY_DISPLAY);
|
||||
android.os.Process.setCanSelfBackground(false);
|
||||
|
||||
synchronized (this) {
|
||||
mService = s;
|
||||
@ -607,6 +608,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
// Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
|
||||
android.os.Process.setThreadPriority(
|
||||
android.os.Process.THREAD_PRIORITY_FOREGROUND);
|
||||
android.os.Process.setCanSelfBackground(false);
|
||||
mPolicy.init(mContext, mService, mPM);
|
||||
|
||||
synchronized (this) {
|
||||
|
@ -1259,6 +1259,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
|
||||
android.os.Process.setThreadPriority(
|
||||
android.os.Process.THREAD_PRIORITY_FOREGROUND);
|
||||
android.os.Process.setCanSelfBackground(false);
|
||||
|
||||
ActivityManagerService m = new ActivityManagerService();
|
||||
|
||||
|
Reference in New Issue
Block a user