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:
Christopher Tate
2010-06-30 17:46:30 -07:00
parent c6e1d88022
commit 160edb3645
5 changed files with 53 additions and 1 deletions

View File

@ -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

View File

@ -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},

View File

@ -80,7 +80,8 @@ 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
: Integer.parseInt(factoryTestStr);

View File

@ -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) {

View File

@ -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();