bug 573669 - Suspend Gecko's event loop when onPause() is called by Android r=vlad
authorBrad Lassey <blassey@mozilla.com>
Tue, 22 Jun 2010 11:22:31 -0400
changeset 44134 62396a6d16a9cea1d296efcd38251406ed9df3a0
parent 44133 20cb75ce742f443f70901471818cd3476a7d02d7
child 44135 aed5499f979d117618416b881b6c56019f94e65a
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs573669
milestone1.9.3a6pre
bug 573669 - Suspend Gecko's event loop when onPause() is called by Android r=vlad
embedding/android/GeckoApp.java
embedding/android/GeckoAppShell.java
widget/src/android/AndroidJNI.cpp
widget/src/android/nsAppShell.cpp
widget/src/android/nsAppShell.h
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -156,31 +156,37 @@ abstract public class GeckoApp
             GeckoAppShell.sendEventToGecko(new GeckoEvent(uri));
             Log.i("GeckoApp","onNewIntent: "+uri);
         }
     }
 
     @Override
     public void onPause()
     {
+
+        Log.i("GeckoApp", "pause");
         GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_PAUSING));
         // The user is navigating away from this activity, but nothing
         // has come to the foreground yet; for Gecko, we may want to
         // stop repainting, for example.
 
         // Whatever we do here should be fast, because we're blocking
         // the next activity from showing up until we finish.
 
         // onPause will be followed by either onResume or onStop.
         super.onPause();
     }
 
     @Override
     public void onResume()
     {
+        Log.i("GeckoApp", "resume");
+        GeckoAppShell.onResume();
+        if (surfaceView != null)
+            surfaceView.mSurfaceNeedsRedraw = true;
         // After an onPause, the activity is back in the foreground.
         // Undo whatever we did in onPause.
         super.onResume();
     }
 
     @Override
     public void onStop()
     {
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -77,16 +77,17 @@ class GeckoAppShell
     // Initialization methods
     public static native void nativeInit();
     public static native void nativeRun(String args);
 
     // helper methods
     public static native void setInitialSize(int width, int height);
     public static native void setSurfaceView(GeckoSurfaceView sv);
     public static native void putenv(String map);
+    public static native void onResume();
 
     // java-side stuff
     public static void loadGeckoLibs() {
         // The package data lib directory isn't placed in ld.so's
         // search path, so we have to manually load libraries that
         // libxul will depend on.  Not ideal.
 
         // MozAlloc
--- a/widget/src/android/AndroidJNI.cpp
+++ b/widget/src/android/AndroidJNI.cpp
@@ -52,16 +52,17 @@ using namespace mozilla;
 /* Forward declare all the JNI methods as extern "C" */
 
 extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *, jclass, jobject event);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject sv);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setInitialSize(JNIEnv *jenv, jclass, int width, int height);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_putenv(JNIEnv *jenv, jclass, jstring map);
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *, jclass);
 }
 
 
 /*
  * Incoming JNI methods
  */
 
 NS_EXPORT void JNICALL
@@ -101,8 +102,15 @@ Java_org_mozilla_gecko_GeckoAppShell_put
         return;
 #ifdef DEBUG
     __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", "putenv(%s)", str);
 #endif
     putenv(strdup(str));
     jenv->ReleaseStringUTFChars(map, str);
     
 }
+
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *jenv, jclass jc)
+{
+    if (nsAppShell::gAppShell)
+        nsAppShell::gAppShell->OnResume();
+}
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -74,16 +74,18 @@ nsIGeolocationUpdate *gLocationCallback 
 
 nsAppShell *nsAppShell::gAppShell = nsnull;
 AndroidGeckoEvent *nsAppShell::gEarlyEvent = nsnull;
 
 nsAppShell::nsAppShell()
     : mQueueLock(nsnull),
       mCondLock(nsnull),
       mQueueCond(nsnull),
+      mPausedLock(nsnull),
+      mPaused(nsnull),
       mNumDraws(0)
 {
     gAppShell = this;
     if (gEarlyEvent) {
         mEventQueue.AppendElement(gEarlyEvent);
         gEarlyEvent = nsnull;
     }
 }
@@ -106,17 +108,19 @@ nsAppShell::Init()
 {
 #ifdef PR_LOGGING
     if (!gWidgetLog)
         gWidgetLog = PR_NewLogModule("Widget");
 #endif
 
     mQueueLock = PR_NewLock();
     mCondLock = PR_NewLock();
+    mPausedLock = PR_NewLock();
     mQueueCond = PR_NewCondVar(mCondLock);
+    mPaused = PR_NewCondVar(mPausedLock);
 
     return nsBaseAppShell::Init();
 }
 
 
 void
 nsAppShell::ScheduleNativeEventCallback()
 {
@@ -247,16 +251,20 @@ nsAppShell::ProcessNextNativeEvent(PRBoo
             appSvc->Quit(nsIAppStartup::eForceQuit);
         break;
     }
 
     case AndroidGeckoEvent::ACTIVITY_PAUSING: {
         nsCOMPtr<nsIObserverService> obsServ =
           mozilla::services::GetObserverService();
         obsServ->NotifyObservers(nsnull, "profile-before-change", nsnull);
+
+        // The OS is sending us to the background, block this thread until 
+        // onResume is called to signal that we're back in the foreground
+        PR_WaitCondVar(mPaused, PR_INTERVAL_NO_TIMEOUT);
         break;
     }
 
     case AndroidGeckoEvent::LOAD_URI: {
         nsCOMPtr<nsICommandLineRunner> cmdline
             (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
         if (!cmdline)
             break;
@@ -341,16 +349,25 @@ nsAppShell::RemoveNextEvent()
         mEventQueue.RemoveElementAt(0);
         if (ae->Type() == AndroidGeckoEvent::DRAW) {
             mNumDraws--;
         }
     }
     PR_Unlock(mQueueLock);
 }
 
+void
+nsAppShell::OnResume()
+{
+    PR_Lock(mPausedLock);
+    PR_NotifyCondVar(mPaused);
+    PR_Unlock(mPausedLock);
+
+}
+
 // Used by IPC code
 namespace mozilla {
 
 bool ProcessNextEvent()
 {
     return nsAppShell::gAppShell->ProcessNextNativeEvent(PR_TRUE) ? true : false;
 }
 
--- a/widget/src/android/nsAppShell.h
+++ b/widget/src/android/nsAppShell.h
@@ -63,24 +63,28 @@ public:
     nsresult Init();
 
     void NotifyNativeEvent();
 
     virtual PRBool ProcessNextNativeEvent(PRBool mayWait);
 
     void PostEvent(mozilla::AndroidGeckoEvent *event);
     void RemoveNextEvent();
+    void OnResume();
+
 protected:
     virtual void ScheduleNativeEventCallback();
     virtual ~nsAppShell();
 
     int mNumDraws;
     PRLock *mQueueLock;
     PRLock *mCondLock;
+    PRLock *mPausedLock;
     PRCondVar *mQueueCond;
+    PRCondVar *mPaused;
     nsTArray<mozilla::AndroidGeckoEvent *> mEventQueue;
 
     mozilla::AndroidGeckoEvent *GetNextEvent();
     mozilla::AndroidGeckoEvent *PeekNextEvent();
 };
 
 #endif // nsAppShell_h__