diff options
-rw-r--r-- | core/java/android/os/Process.java | 9 | ||||
-rw-r--r-- | core/jni/android_util_Process.cpp | 39 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 3 | ||||
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 2 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 1 |
5 files changed, 53 insertions, 1 deletions
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 5640a06..f695dbb 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -626,6 +626,15 @@ public class Process { 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 * @param tid The indentifier of the thread/process to change. diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 68be741..7c99271 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -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}, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 7130636..c01680e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index bf86b23..483f9eb 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -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) { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 46861ee..93122c4 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -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(); |