Bug 730890 - Install and run an Android Looper on Gecko main thread r=cjones

This commit is contained in:
James Willcox 2012-05-03 10:53:31 -04:00
Родитель 7db0b87ef1
Коммит 578bae396e
5 изменённых файлов: 67 добавлений и 12 удалений

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

@ -67,20 +67,11 @@ anp_event_postEvent(NPP inst, const ANPEvent* event)
{
LOG("%s", __PRETTY_FUNCTION__);
JNIEnv* env = GetJNIForThread();
if (!env)
return;
if (!mozilla::AndroidBridge::Bridge()) {
LOG("no bridge in %s!!!!", __PRETTY_FUNCTION__);
return;
}
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(inst->ndata);
NPPluginFuncs* pluginFunctions = pinst->GetPlugin()->PluginFuncs();
mozilla::AndroidBridge::Bridge()->PostToJavaThread(env,
new PluginEventRunnable(inst, const_cast<ANPEvent*>(event), pluginFunctions),
true);
PluginEventRunnable* e = new PluginEventRunnable(inst, const_cast<ANPEvent*>(event), pluginFunctions);
NS_DispatchToMainThread(e);
LOG("returning from %s", __PRETTY_FUNCTION__);
}

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

@ -47,6 +47,10 @@
#include "base/logging.h"
#include "base/scoped_nsautorelease_pool.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
using mozilla::ipc::DoWorkRunnable;
using mozilla::ipc::MessagePump;
using mozilla::ipc::MessagePumpForChildProcess;
@ -115,6 +119,13 @@ MessagePump::Run(MessagePump::Delegate* aDelegate)
if (!keep_running_)
break;
#ifdef MOZ_WIDGET_ANDROID
// This processes messages in the Android Looper. Note that we only
// get here if the normal Gecko event loop has been awoken above.
// Bug 750713
AndroidBridge::Bridge()->PumpMessageLoop();
#endif
did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
if (did_work && delayed_work_time_.is_null())

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

@ -155,6 +155,8 @@ public class GeckoAppShell
private static boolean mLocationHighAccuracy = false;
private static Handler sGeckoHandler;
/* The Android-side API: API methods that Android calls */
// Initialization methods
@ -264,6 +266,10 @@ public class GeckoAppShell
return GeckoApp.mAppContext.mMainHandler;
}
public static Handler getGeckoHandler() {
return sGeckoHandler;
}
public static Handler getHandler() {
return GeckoBackgroundThread.getHandler();
}
@ -458,6 +464,9 @@ public class GeckoAppShell
}
public static void runGecko(String apkPath, String args, String url, String type, boolean restoreSession) {
Looper.prepare();
sGeckoHandler = new Handler();
// run gecko -- it will spawn its own thread
GeckoAppShell.nativeInit();
@ -2120,6 +2129,28 @@ public class GeckoAppShell
GeckoScreenOrientationListener.getInstance().unlockScreenOrientation();
}
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 a RuntimeException. 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 RuntimeException();
}
});
try {
Looper.loop();
} catch(Exception ex) {}
}
static class AsyncResultHandler extends GeckoApp.FilePickerResultHandler {
private long mId;
AsyncResultHandler(long id) {

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

@ -215,6 +215,8 @@ AndroidBridge::Init(JNIEnv *jEnv,
jSurfacePointerField = jEnv->GetFieldID(jSurfaceClass, "mNativeSurface", "I");
#ifdef MOZ_JAVA_COMPOSITOR
jPumpMessageLoop = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "pumpMessageLoop", "()V");
jAddPluginView = jEnv->GetStaticMethodID(jGeckoAppShellClass, "addPluginView", "(Landroid/view/View;IIII)V");
jCreateSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "createSurface", "()Landroid/view/Surface;");
jShowSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "showSurface", "(Landroid/view/Surface;IIIIZZ)V");
@ -2186,6 +2188,23 @@ AndroidBridge::UnlockScreenOrientation()
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jUnlockScreenOrientation);
}
void
AndroidBridge::PumpMessageLoop()
{
#if MOZ_JAVA_COMPOSITOR
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame frame(env);
if ((void*)pthread_self() != mThread)
return;
env->CallStaticVoidMethod(mGeckoAppShellClass, jPumpMessageLoop);
#endif
}
/* attribute nsIAndroidBrowserApp browserApp; */
NS_IMETHODIMP nsAndroidBridge::GetBrowserApp(nsIAndroidBrowserApp * *aBrowserApp)
{

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

@ -451,6 +451,8 @@ public:
void LockScreenOrientation(const dom::ScreenOrientationWrapper& aOrientation);
void UnlockScreenOrientation();
void PumpMessageLoop();
protected:
static AndroidBridge *sBridge;
@ -569,6 +571,7 @@ protected:
jmethodID jDisableScreenOrientationNotifications;
jmethodID jLockScreenOrientation;
jmethodID jUnlockScreenOrientation;
jmethodID jPumpMessageLoop;
// For native surface stuff
jclass jSurfaceClass;