Bug 889881 - Use IdleHandler to make MessageQueue.next() not block; r=blassey

This commit is contained in:
Jim Chen 2013-07-09 16:25:55 -04:00
Родитель e56ee2b07a
Коммит ab6dffe101
2 изменённых файлов: 25 добавлений и 9 удалений

Просмотреть файл

@ -56,6 +56,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
@ -293,6 +294,19 @@ public class GeckoAppShell
}
public static void runGecko(String apkPath, String args, String url, String type) {
// Preparation for pumpMessageLoop()
MessageQueue.IdleHandler idleHandler = new MessageQueue.IdleHandler() {
@Override public boolean queueIdle() {
Handler geckoHandler = ThreadUtils.getGeckoHandler();
Message idleMsg = Message.obtain(geckoHandler);
// Use |Message.obj == GeckoHandler| to identify our "queue is empty" message
idleMsg.obj = geckoHandler;
geckoHandler.sendMessageAtFrontOfQueue(idleMsg);
// Keep this IdleHandler
return true;
}
};
Looper.myQueue().addIdleHandler(idleHandler);
// run gecko -- it will spawn its own thread
GeckoAppShell.nativeInit();
@ -321,6 +335,9 @@ public class GeckoAppShell
// and go
GeckoLoader.nativeRun(combinedArgs);
// Remove pumpMessageLoop() idle handler
Looper.myQueue().removeIdleHandler(idleHandler);
}
// Called on the UI thread after Gecko loads.
@ -2463,10 +2480,16 @@ public class GeckoAppShell
}
public static boolean pumpMessageLoop() {
Handler geckoHandler = ThreadUtils.getGeckoHandler();
MessageQueue mq = Looper.myQueue();
Message msg = getNextMessageFromQueue(mq);
if (msg == null)
return false;
if (msg.getTarget() == geckoHandler && msg.obj == geckoHandler) {
// Our "queue is empty" message; see runGecko()
msg.recycle();
return false;
}
if (msg.getTarget() == null)
Looper.myLooper().quit();
else

Просмотреть файл

@ -803,21 +803,14 @@ NS_EXPORT jobject JNICALL
Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv* jenv, jclass, jobject queue)
{
static jclass jMessageQueueCls = nullptr;
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;");
}
if (!jMessageQueueCls || !jMessagesField || !jNextMethod)
if (!jMessageQueueCls || !jNextMethod)
return NULL;
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;
return jenv->CallObjectMethod(queue, jNextMethod);
}
NS_EXPORT void JNICALL