diff --git a/mobile/android/base/GeckoActivity.java.in b/mobile/android/base/GeckoActivity.java.in index 1b8c2d9b0fa1..f8fb7cdbe1fd 100644 --- a/mobile/android/base/GeckoActivity.java.in +++ b/mobile/android/base/GeckoActivity.java.in @@ -2,11 +2,23 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#filter substitution + package org.mozilla.gecko; import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; + +interface GeckoActivityStatus { + public boolean isGeckoActivityOpened(); + public boolean isFinishing(); // typically from android.app.Activity +}; + +public class GeckoActivity extends Activity implements GeckoActivityStatus { + // has this activity recently started another Gecko activity? + private boolean mGeckoActivityOpened = false; -public class GeckoActivity extends Activity { @Override public void onPause() { super.onPause(); @@ -22,9 +34,39 @@ public class GeckoActivity extends Activity { if (getApplication() instanceof GeckoApplication) { ((GeckoApplication) getApplication()).onActivityResume(this); + mGeckoActivityOpened = false; } } + @Override + public void startActivity(Intent intent) { + checkIfGeckoActivity(intent); + super.startActivity(intent); + } + + @Override + public void startActivityForResult(Intent intent, int request) { + checkIfGeckoActivity(intent); + super.startActivityForResult(intent, request); + } + + private void checkIfGeckoActivity(Intent intent) { + // Whenever we call our own activity, the component and it's package name is set. + // If we call an activity from another package, or an open intent (leaving android to resolve) + // component has a different package name or it is null. + ComponentName component = intent.getComponent(); + mGeckoActivityOpened = false; + if (component != null && + component.getPackageName() != null && + component.getPackageName().equals("@ANDROID_PACKAGE_NAME@")) { + mGeckoActivityOpened = true; + } + } + + public boolean isGeckoActivityOpened() { + return mGeckoActivityOpened; + } + public boolean isApplicationInBackground() { return ((GeckoApplication) getApplication()).isApplicationInBackground(); } diff --git a/mobile/android/base/GeckoApplication.java b/mobile/android/base/GeckoApplication.java index c2d094e445f3..d47df61821e4 100644 --- a/mobile/android/base/GeckoApplication.java +++ b/mobile/android/base/GeckoApplication.java @@ -10,6 +10,7 @@ public class GeckoApplication extends Application { private boolean mInited; private boolean mInBackground; + private boolean mPausedGecko; private LightweightTheme mLightweightTheme; @@ -32,17 +33,28 @@ public class GeckoApplication extends Application { mInited = true; } - protected void onActivityPause(GeckoActivity activity) { + protected void onActivityPause(GeckoActivityStatus activity) { mInBackground = true; - GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true)); + if ((activity.isFinishing() == false) && + (activity.isGeckoActivityOpened() == false)) { + // Notify Gecko that we are pausing; the cache service will be + // shutdown, closing the disk cache cleanly. If the android + // low memory killer subsequently kills us, the disk cache will + // be left in a consistent state, avoiding costly cleanup and + // re-creation. + GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true)); + mPausedGecko = true; + } GeckoConnectivityReceiver.getInstance().stop(); GeckoNetworkManager.getInstance().stop(); } - protected void onActivityResume(GeckoActivity activity) { - if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) + protected void onActivityResume(GeckoActivityStatus activity) { + if (mPausedGecko) { GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true)); + mPausedGecko = false; + } GeckoConnectivityReceiver.getInstance().start(); GeckoNetworkManager.getInstance().start(); diff --git a/mobile/android/base/GeckoPreferences.java b/mobile/android/base/GeckoPreferences.java index ed9e75db76b7..6432ffed38dd 100644 --- a/mobile/android/base/GeckoPreferences.java +++ b/mobile/android/base/GeckoPreferences.java @@ -43,7 +43,7 @@ import java.util.ArrayList; public class GeckoPreferences extends PreferenceActivity - implements OnPreferenceChangeListener, GeckoEventListener + implements OnPreferenceChangeListener, GeckoEventListener, GeckoActivityStatus { private static final String LOGTAG = "GeckoPreferences"; @@ -85,6 +85,24 @@ public class GeckoPreferences unregisterEventListener("Sanitize:Finished"); } + @Override + public void onPause() { + super.onPause(); + + if (getApplication() instanceof GeckoApplication) { + ((GeckoApplication) getApplication()).onActivityPause(this); + } + } + + @Override + public void onResume() { + super.onResume(); + + if (getApplication() instanceof GeckoApplication) { + ((GeckoApplication) getApplication()).onActivityResume(this); + } + } + public void handleMessage(String event, JSONObject message) { try { if (event.equals("Sanitize:Finished")) { @@ -445,4 +463,8 @@ public class GeckoPreferences private void unregisterEventListener(String event) { GeckoAppShell.getEventDispatcher().unregisterEventListener(event, this); } + + public boolean isGeckoActivityOpened() { + return false; + } }