bug 633239 - event loop responsiveness for Android r=dougt
authorBrad Lassey <blassey@mozilla.com>
Thu, 04 Aug 2011 03:32:57 -0400
changeset 80489 78e519331f400178965ac51e875bd805736d0043
parent 80488 58563c49a53197379a83eb81233d11b655cfd082
child 80490 1595eb996964849255d4a18b1756bb6cfd661c54
push idunknown
push userunknown
push dateunknown
reviewersdougt
bugs633239
milestone10.0a1
bug 633239 - event loop responsiveness for Android r=dougt
configure.in
embedding/android/GeckoAppShell.java
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
--- a/configure.in
+++ b/configure.in
@@ -4643,16 +4643,17 @@ cairo-uikit)
 
 cairo-android)
     AC_DEFINE(MOZ_WIDGET_ANDROID)
     MOZ_WIDGET_TOOLKIT=android
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
+    MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
 
 esac
 
 AC_SUBST(MOZ_PDF_PRINTING)
 if test "$MOZ_PDF_PRINTING"; then
    PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
    AC_DEFINE(MOZ_PDF_PRINTING)
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -1562,9 +1562,28 @@ public class GeckoAppShell
         Log.i("GeckoAppJava", "closeCamera() on thread " + Thread.currentThread().getId());
         if (sCamera != null) {
             sCamera.stopPreview();
             sCamera.release();
             sCamera = null;
             sCameraBuffer = null;
         }
     }
+
+
+    static SynchronousQueue<Date> sTracerQueue = new SynchronousQueue<Date>();
+    public static void fireAndWaitForTracerEvent() {
+        getMainHandler().post(new Runnable() { 
+                public void run() {
+                    try {
+                        sTracerQueue.put(new Date());
+                    } catch(InterruptedException ie) {
+                        Log.w("GeckoAppShell", "exception firing tracer", ie);
+                    }
+                }
+        });
+        try {
+            sTracerQueue.take();
+        } catch(InterruptedException ie) {
+            Log.w("GeckoAppShell", "exception firing tracer", ie);
+        }
+    }
 }
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -43,16 +43,17 @@
 #include <prthread.h>
 #include "nsXPCOMStrings.h"
 
 #include "AndroidBridge.h"
 #include "nsAppShell.h"
 #include "nsOSHelperAppService.h"
 #include "nsWindow.h"
 #include "mozilla/Preferences.h"
+#include "nsThreadUtils.h"
 
 #ifdef DEBUG
 #define ALOG_BRIDGE(args...) ALOG(args)
 #else
 #define ALOG_BRIDGE(args...)
 #endif
 
 #define IME_FULLSCREEN_PREF "widget.ime.android.landscape_fullscreen"
@@ -141,16 +142,17 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jPerformHapticFeedback = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "performHapticFeedback", "(Z)V");
     jSetKeepScreenOn = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setKeepScreenOn", "(Z)V");
     jIsNetworkLinkUp = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkUp", "()Z");
     jIsNetworkLinkKnown = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkKnown", "()Z");
     jSetSelectedLocale = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setSelectedLocale", "(Ljava/lang/String;)V");
     jScanMedia = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V");
     jGetSystemColors = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getSystemColors", "()[I");
     jGetIconForExtension = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getIconForExtension", "(Ljava/lang/String;I)[B");
+    jFireAndWaitForTracerEvent = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "fireAndWaitForTracerEvent", "()V");   
     jCreateShortcut = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
     jGetShowPasswordSetting = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getShowPasswordSetting", "()Z");
     jPostToJavaThread = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "postToJavaThread", "(Z)V");
     jInitCamera = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "initCamera", "(Ljava/lang/String;III)[I");
     jCloseCamera = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "closeCamera", "()V");
 
     jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
     jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
@@ -1005,16 +1007,87 @@ AndroidBridge::OpenGraphicsLibraries()
 
             mHasNativeWindowAccess = ANativeWindow_fromSurface && ANativeWindow_release && ANativeWindow_lock && ANativeWindow_unlockAndPost;
 
             ALOG_BRIDGE("Successfully opened libandroid.so, have native window access? %d", mHasNativeWindowAccess);
         }
     }
 }
 
+void
+AndroidBridge::FireAndWaitForTracerEvent() {
+    mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, 
+                                  jFireAndWaitForTracerEvent);
+}
+
+
+namespace mozilla {
+    class TracerRunnable : public nsRunnable{
+    public:
+        TracerRunnable() {
+            mTracerLock = new Mutex("TracerRunnable");
+            mTracerCondVar = new CondVar(*mTracerLock, "TracerRunnable");
+            mMainThread = do_GetMainThread();
+            
+        }
+        ~TracerRunnable() {
+            delete mTracerCondVar;
+            delete mTracerLock;
+            mTracerLock = nsnull;
+            mTracerCondVar = nsnull;
+        }
+
+        virtual nsresult Run() {
+            MutexAutoLock lock(*mTracerLock);
+            if (!AndroidBridge::Bridge())
+                return NS_OK;
+            
+            AndroidBridge::Bridge()->FireAndWaitForTracerEvent();
+            mHasRun = PR_TRUE;
+            mTracerCondVar->Notify();
+            return NS_OK;
+        }
+        
+        bool Fire() {
+            if (!mTracerLock || !mTracerCondVar)
+                return false;
+            MutexAutoLock lock(*mTracerLock);
+            mHasRun = PR_FALSE;
+            mMainThread->Dispatch(this, NS_DISPATCH_NORMAL);
+            while (!mHasRun)
+                mTracerCondVar->Wait();
+            return true;
+        }
+    private:
+        Mutex* mTracerLock;
+        CondVar* mTracerCondVar;
+        PRBool mHasRun;
+        nsCOMPtr<nsIThread> mMainThread;
+
+    };
+    nsCOMPtr<TracerRunnable> sTracerRunnable;
+
+    bool InitWidgetTracing() {
+        if (!sTracerRunnable)
+            sTracerRunnable = new TracerRunnable();
+        return true;
+    }
+
+    void CleanUpWidgetTracing() {
+        if (sTracerRunnable)
+            delete sTracerRunnable;
+        sTracerRunnable = nsnull;
+    }
+
+    bool FireAndWaitForTracerEvent() {
+        if (sTracerRunnable)
+            return sTracerRunnable->Fire();
+        return false;
+    }
+}
 bool
 AndroidBridge::HasNativeBitmapAccess()
 {
     OpenGraphicsLibraries();
 
     return mHasNativeBitmapAccess;
 }
 
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -208,16 +208,18 @@ public:
     void SetSelectedLocale(const nsAString&);
 
     void GetSystemColors(AndroidSystemColors *aColors);
 
     void GetIconForExtension(const nsACString& aFileExt, PRUint32 aIconSize, PRUint8 * const aBuf);
 
     bool GetShowPasswordSetting();
 
+    void FireAndWaitForTracerEvent();
+
     struct AutoLocalJNIFrame {
         AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) {
             // Make sure there is enough space to store a local ref to the
             // exception.  I am not completely sure this is needed, but does
             // not hurt.
             AndroidBridge::Bridge()->JNI()->PushLocalFrame(mEntries + 1);
         }
         // Note! Calling Purge makes all previous local refs created in
@@ -345,16 +347,17 @@ protected:
     jmethodID jPerformHapticFeedback;
     jmethodID jSetKeepScreenOn;
     jmethodID jIsNetworkLinkUp;
     jmethodID jIsNetworkLinkKnown;
     jmethodID jSetSelectedLocale;
     jmethodID jScanMedia;
     jmethodID jGetSystemColors;
     jmethodID jGetIconForExtension;
+    jmethodID jFireAndWaitForTracerEvent;
     jmethodID jCreateShortcut;
     jmethodID jGetShowPasswordSetting;
     jmethodID jPostToJavaThread;
     jmethodID jInitCamera;
     jmethodID jCloseCamera;
 
     // stuff we need for CallEglCreateWindowSurface
     jclass jEGLSurfaceImplClass;