bug 759146 - Looper throws uncaught exception on (some?) HTC Sense 4.0 phones (HTC Evo 4G LTE, HTC J, etc) r=snorp

This commit is contained in:
Brad Lassey 2012-05-31 20:07:07 -04:00
parent ec1cdcb284
commit c766b61ee2
3 changed files with 30 additions and 19 deletions

View File

@ -148,6 +148,7 @@ public class GeckoAppShell
public static native void loadSQLiteLibsNative(String apkName, boolean shouldExtract);
public static native void loadNSSLibsNative(String apkName, boolean shouldExtract);
public static native void onChangeNetworkLinkStatus(String status);
public static native Message getNextMessageFromQueue(MessageQueue queue);
public static void registerGlobalExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@ -2105,25 +2106,15 @@ public class GeckoAppShell
}
public static void pumpMessageLoop() {
// We're going to run the Looper below, but we need a way to break out, so
// we post this Runnable that throws an AssertionError. This causes the loop
// to exit without marking the Looper as dead. The Runnable is added to the
// end of the queue, so it will be executed after anything
// else that has been added prior.
//
// A more civilized method would obviously be preferred. Looper.quit(),
// however, marks the Looper as dead and it cannot be prepared or run
// again. And since you can only have a single Looper per thread,
// here we are.
sGeckoHandler.post(new Runnable() {
public void run() {
throw new AssertionError();
}
});
try {
Looper.loop();
} catch(Throwable ex) {}
MessageQueue mq = Looper.myQueue();
Message msg = getNextMessageFromQueue(mq);
if (msg == null)
return;
if (msg.getTarget() == null)
Looper.myLooper().quit();
else
msg.getTarget().dispatchMessage(msg);
msg.recycle();
}
static class AsyncResultHandler extends GeckoApp.FilePickerResultHandler {

View File

@ -320,6 +320,7 @@ SHELL_WRAPPER3(notifyReadingMessageListFailed, jint, jint, jlong)
SHELL_WRAPPER2(notifyFilePickerResult, jstring, jlong)
SHELL_WRAPPER1_WITH_RETURN(getSurfaceBits, jobject, jobject)
SHELL_WRAPPER1(onFullScreenPluginHidden, jobject)
SHELL_WRAPPER1_WITH_RETURN(getNextMessageFromQueue, jobject, jobject)
static void * xul_handle = NULL;
static void * sqlite_handle = NULL;
@ -738,6 +739,7 @@ loadGeckoLibs(const char *apkName)
GETFUNC(notifyFilePickerResult);
GETFUNC(getSurfaceBits);
GETFUNC(onFullScreenPluginHidden);
GETFUNC(getNextMessageFromQueue);
#undef GETFUNC
sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
gettimeofday(&t1, 0);

View File

@ -819,6 +819,24 @@ Java_org_mozilla_gecko_GeckoAppShell_notifyReadingMessageListFailed(JNIEnv* jenv
PRUint64 mProcessId;
};
NS_EXPORT jobject JNICALL
Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv* jenv, jclass, jobject queue)
{
static jclass jMessageQueueCls = nsnull;
static jfieldID jMessagesField;
static jmethodID jNextMethod;
if (!jMessageQueueCls) {
jMessageQueueCls = (jclass) jenv->NewGlobalRef(jenv->FindClass("android/os/MessageQueue"));
jMessagesField = jenv->GetFieldID(jMessageQueueCls, "mMessages", "Landroid/os/Message;");
jNextMethod = jenv->GetMethodID(jMessageQueueCls, "next", "()Landroid/os/Message;");
}
jobject msg = jenv->GetObjectField(queue, jMessagesField);
// if queue.mMessages is null, queue.next() will block, which we don't want
if (!msg)
return msg;
msg = jenv->CallObjectMethod(queue, jNextMethod);
return msg;
}
nsCOMPtr<nsIRunnable> runnable =
new NotifyReadListFailedRunnable(aError, aRequestId, aProcessId);