Detect system-wide safe mode and configure the VM accordingly.
Use pthread_cond_wait instead of timed wait for the system_server process to
wait on the go-ahead JIT signal. If the phone is booted under system-wide safe
mode, such signal will never come so all VM instances (including the system
server) will run in the interpreter-only mode.
Bug: 2267590
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 484f9a3..8297131 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -397,13 +397,41 @@
* up code isn't worth compiling. We'll resume when the framework
* signals us that the first screen draw has happened, or the timer
* below expires (to catch daemons).
+ *
+ * There is a theoretical race between the callback to
+ * VMRuntime.startJitCompiation and when the compiler thread reaches this
+ * point. In case the callback happens earlier, in order not to permanently
+ * hold the system_server (which is not using the timed wait) in
+ * interpreter-only mode we bypass the delay here.
*/
- if (gDvmJit.runningInAndroidFramework) {
- dvmLockMutex(&gDvmJit.compilerLock);
- // TUNING: experiment with the delay & perhaps make it target-specific
- dvmRelativeCondWait(&gDvmJit.compilerQueueActivity,
- &gDvmJit.compilerLock, 3000, 0);
- dvmUnlockMutex(&gDvmJit.compilerLock);
+ if (gDvmJit.runningInAndroidFramework &&
+ !gDvmJit.alreadyEnabledViaFramework) {
+ /*
+ * If the current VM instance is the system server (detected by having
+ * 0 in gDvm.systemServerPid), we will use the indefinite wait on the
+ * conditional variable to determine whether to start the JIT or not.
+ * If the system server detects that the whole system is booted in
+ * safe mode, the conditional variable will never be signaled and the
+ * system server will remain in the interpreter-only mode. All
+ * subsequent apps will be started with the --enable-safemode flag
+ * explicitly appended.
+ */
+ if (gDvm.systemServerPid == 0) {
+ dvmLockMutex(&gDvmJit.compilerLock);
+ pthread_cond_wait(&gDvmJit.compilerQueueActivity,
+ &gDvmJit.compilerLock);
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ LOGD("JIT started for system_server");
+ } else {
+ dvmLockMutex(&gDvmJit.compilerLock);
+ /*
+ * TUNING: experiment with the delay & perhaps make it
+ * target-specific
+ */
+ dvmRelativeCondWait(&gDvmJit.compilerQueueActivity,
+ &gDvmJit.compilerLock, 3000, 0);
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ }
if (gDvmJit.haltCompilerThread) {
return NULL;
}