зеркало из https://github.com/mozilla/gecko-dev.git
Bug 624652 - Add memory watcher to reduce the chance of ooming on the Nexus S. r=mwu/cjones. a=blocking-fennec
--HG-- extra : rebase_source : faf23b65fe8b5c64080c1ee3f6d4794e8837097d
This commit is contained in:
Родитель
73ae517d85
Коммит
2ed6ba5845
|
@ -75,6 +75,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsICrashReporter.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#endif
|
||||
|
||||
|
@ -82,10 +83,13 @@
|
|||
#include "mozilla/dom/StorageParent.h"
|
||||
#include "nsAccelerometer.h"
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::net;
|
||||
using namespace mozilla::places;
|
||||
using mozilla::MonitorAutoEnter;
|
||||
using base::KillProcess;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -365,6 +369,19 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
|
||||
// listening for memory pressure event
|
||||
if (!strcmp(aTopic, "memory-pressure")) {
|
||||
NS_ConvertUTF16toUTF8 dataStr(aData);
|
||||
const char *deathPending = dataStr.get();
|
||||
|
||||
if (!strcmp(deathPending, "oom-kill")) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
nsCOMPtr<nsICrashReporter> cr = do_GetService("@mozilla.org/toolkit/crash-reporter;1");
|
||||
if (cr) {
|
||||
cr->AnnotateCrashReport(NS_LITERAL_CSTRING("oom"), NS_LITERAL_CSTRING("true"));
|
||||
}
|
||||
#endif
|
||||
KillProcess(OtherProcess(), 0, false);
|
||||
}
|
||||
else
|
||||
SendFlushMemory(nsDependentString(aData));
|
||||
}
|
||||
// listening for remotePrefs...
|
||||
|
|
|
@ -70,6 +70,7 @@ abstract public class GeckoApp
|
|||
public static GeckoApp mAppContext;
|
||||
public static boolean mFullscreen = false;
|
||||
static Thread mLibLoadThread = null;
|
||||
private static MemoryWatcher mMemoryWatcher = null;
|
||||
|
||||
enum LaunchState {PreLaunch, Launching, WaitButton,
|
||||
Launched, GeckoRunning, GeckoExiting};
|
||||
|
@ -212,7 +213,9 @@ abstract public class GeckoApp
|
|||
else
|
||||
surfaceView.mSplashStatusMsg =
|
||||
getResources().getString(R.string.splash_screen_label);
|
||||
mLibLoadThread.start();
|
||||
mLibLoadThread.start();
|
||||
|
||||
mMemoryWatcher = new MemoryWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -272,6 +275,8 @@ abstract public class GeckoApp
|
|||
|
||||
// onPause will be followed by either onResume or onStop.
|
||||
super.onPause();
|
||||
|
||||
mMemoryWatcher.StopMemoryWatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -288,6 +293,8 @@ abstract public class GeckoApp
|
|||
if (checkLaunchState(LaunchState.PreLaunch) ||
|
||||
checkLaunchState(LaunchState.Launching))
|
||||
onNewIntent(getIntent());
|
||||
|
||||
mMemoryWatcher.StartMemoryWatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -346,7 +353,9 @@ abstract public class GeckoApp
|
|||
@Override
|
||||
public void onLowMemory()
|
||||
{
|
||||
Log.i("GeckoApp", "low memory");
|
||||
// if you change this handler, please take a look at
|
||||
// MemoryWatcher too.
|
||||
Log.e("GeckoApp", "low memory");
|
||||
if (checkLaunchState(LaunchState.GeckoRunning))
|
||||
GeckoAppShell.onLowMemory();
|
||||
super.onLowMemory();
|
||||
|
|
|
@ -97,6 +97,7 @@ class GeckoAppShell
|
|||
public static native void putenv(String map);
|
||||
public static native void onResume();
|
||||
public static native void onLowMemory();
|
||||
public static native void onCriticalOOM();
|
||||
public static native void callObserver(String observerKey, String topic, String data);
|
||||
public static native void removeObserver(String observerKey);
|
||||
public static native void loadLibs(String apkName, boolean shouldExtract);
|
||||
|
|
|
@ -53,6 +53,7 @@ JAVAFILES = \
|
|||
GeckoSurfaceView.java \
|
||||
GeckoInputConnection.java \
|
||||
AlertNotification.java \
|
||||
MemoryWatcher.java \
|
||||
$(NULL)
|
||||
|
||||
PROCESSEDJAVAFILES = \
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.os.*;
|
||||
import android.app.*;
|
||||
import android.app.ActivityManager.*;
|
||||
import android.util.*;
|
||||
|
||||
|
||||
// Memory Watcher
|
||||
//
|
||||
// the onLowMemory method is not called on the foreground
|
||||
// activity. Hence we need something that monitors memory
|
||||
// growth, and broadcasts onLowMemory when we get low on
|
||||
// resources. We can also use this to test to see if the
|
||||
// system is responsive. For example, if a call to get
|
||||
// available memory takes too much time, we can assume that
|
||||
// the system is unstable and we should try our best to reduce
|
||||
// resources. Much of this is a hack and should only be used
|
||||
// on devices that don't kill us during low memory. Forgive
|
||||
// me.
|
||||
|
||||
public class MemoryWatcher extends Handler
|
||||
{
|
||||
private static final long MEMORY_WATCHER_INTERVAL = 2000;
|
||||
private static final long MEMORY_WATCHER_INTERVAL_DELAY_FACTOR = 5;
|
||||
private static final long MEMORY_WATCHER_LOW_MEMORY_THRESHOLD = 39000000;
|
||||
private static final long MEMORY_WATCHER_CRITICAL_MEMORY_THRESHOLD = 30000000;
|
||||
private static final long MEMORY_WATCHER_CRITICAL_RESPONSE_THRESHOLD = 200; // in ms
|
||||
|
||||
private Handler mMemoryWatcherHandler;
|
||||
private ActivityManager mActivityManager;
|
||||
private MemoryInfo mMemoryInfo;
|
||||
private boolean mMemoryWatcherKeepGoing;
|
||||
private boolean mMemoryWatcherEnabled = false;
|
||||
|
||||
public MemoryWatcher(GeckoApp app) {
|
||||
if (android.os.Build.MODEL.equals("Nexus S") == false)
|
||||
return;
|
||||
mMemoryWatcherEnabled = true;
|
||||
|
||||
mMemoryWatcherKeepGoing = true;
|
||||
mMemoryInfo = new MemoryInfo();
|
||||
mActivityManager = (ActivityManager) app.getSystemService("activity");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
mActivityManager.getMemoryInfo(mMemoryInfo);
|
||||
long took = System.currentTimeMillis() - startTime;
|
||||
|
||||
/*
|
||||
Log.w("GeckoApp", String.format("OOM_CHECKER %d %d %b %s\n",
|
||||
mMemoryInfo.availMem,
|
||||
mMemoryInfo.threshold,
|
||||
mMemoryInfo.lowMemory,
|
||||
("took " + took + "ms")));
|
||||
*/
|
||||
|
||||
// We will adjust the next time this is called if
|
||||
// we fire a memory event.
|
||||
long nextInterval = MEMORY_WATCHER_INTERVAL;
|
||||
|
||||
// if this call too long, something is very
|
||||
// wrong with the device. fire a critical
|
||||
// notification and hope things get better.
|
||||
if (took > MEMORY_WATCHER_CRITICAL_RESPONSE_THRESHOLD ||
|
||||
mMemoryInfo.availMem < MEMORY_WATCHER_CRITICAL_MEMORY_THRESHOLD) {
|
||||
GeckoAppShell.onCriticalOOM();
|
||||
nextInterval *= MEMORY_WATCHER_INTERVAL_DELAY_FACTOR;
|
||||
}
|
||||
else if (mMemoryInfo.lowMemory ||
|
||||
mMemoryInfo.availMem < MEMORY_WATCHER_LOW_MEMORY_THRESHOLD) {
|
||||
GeckoAppShell.onLowMemory();
|
||||
nextInterval *= MEMORY_WATCHER_INTERVAL_DELAY_FACTOR;
|
||||
}
|
||||
|
||||
if (mMemoryWatcherKeepGoing == true)
|
||||
this.sendEmptyMessageDelayed(0, nextInterval);
|
||||
}
|
||||
|
||||
public void StartMemoryWatcher() {
|
||||
if (mMemoryWatcherEnabled == false)
|
||||
return;
|
||||
mMemoryWatcherKeepGoing = true;
|
||||
sendEmptyMessageDelayed(0, MEMORY_WATCHER_INTERVAL);
|
||||
}
|
||||
|
||||
public void StopMemoryWatcher() {
|
||||
if (mMemoryWatcherEnabled == false)
|
||||
return;
|
||||
mMemoryWatcherKeepGoing = false;
|
||||
removeMessages(0);
|
||||
}
|
||||
}
|
|
@ -236,6 +236,7 @@ SHELL_WRAPPER1(notifyGeckoOfEvent, jobject)
|
|||
SHELL_WRAPPER1(setSurfaceView, jobject)
|
||||
SHELL_WRAPPER0(onResume)
|
||||
SHELL_WRAPPER0(onLowMemory)
|
||||
SHELL_WRAPPER0(onCriticalOOM)
|
||||
SHELL_WRAPPER3(callObserver, jstring, jstring, jstring)
|
||||
SHELL_WRAPPER1(removeObserver, jstring)
|
||||
SHELL_WRAPPER1(onChangeNetworkLinkStatus, jstring)
|
||||
|
@ -666,6 +667,7 @@ loadLibs(const char *apkName)
|
|||
GETFUNC(setSurfaceView);
|
||||
GETFUNC(onResume);
|
||||
GETFUNC(onLowMemory);
|
||||
GETFUNC(onCriticalOOM);
|
||||
GETFUNC(callObserver);
|
||||
GETFUNC(removeObserver);
|
||||
GETFUNC(onChangeNetworkLinkStatus);
|
||||
|
|
|
@ -51,6 +51,11 @@
|
|||
#include "mozilla/Services.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsICrashReporter.h"
|
||||
#endif
|
||||
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/* Forward declare all the JNI methods as extern "C" */
|
||||
|
@ -61,6 +66,7 @@ extern "C" {
|
|||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject sv);
|
||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *, jclass);
|
||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *, jclass);
|
||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onCriticalOOM(JNIEnv *, jclass);
|
||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_callObserver(JNIEnv *, jclass, jstring observerKey, jstring topic, jstring data);
|
||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey);
|
||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *, jclass, jstring status);
|
||||
|
@ -101,6 +107,17 @@ Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *jenv, jclass jc)
|
|||
}
|
||||
}
|
||||
|
||||
NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_onCriticalOOM(JNIEnv *jenv, jclass jc)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoAppShell", "Critical OOM reached!");
|
||||
if (nsAppShell::gAppShell) {
|
||||
nsAppShell::gAppShell->NotifyObservers(nsnull,
|
||||
"memory-pressure",
|
||||
NS_LITERAL_STRING("oom-kill").get());
|
||||
}
|
||||
}
|
||||
|
||||
NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *jenv, jclass jc)
|
||||
{
|
||||
|
|
|
@ -67,6 +67,12 @@
|
|||
* This will be passed as the extra data when the pressure
|
||||
* observer has been asked to flush because a malloc() or
|
||||
* realloc() has failed.
|
||||
*
|
||||
* "oom-kill"
|
||||
* This will be passed as the extra data when the pressure
|
||||
* observer notices that the application will crash or the
|
||||
* system will hang if immediate steps are not taken to
|
||||
* free as much as possible.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(59e7e77a-38e4-11d4-8cf5-0060b0fc14a3)]
|
||||
|
|
Загрузка…
Ссылка в новой задаче