diff --git a/mobile/android/base/MemoryMonitor.java b/mobile/android/base/MemoryMonitor.java index 189af94d621..34182bf55d6 100644 --- a/mobile/android/base/MemoryMonitor.java +++ b/mobile/android/base/MemoryMonitor.java @@ -148,17 +148,27 @@ class MemoryMonitor extends BroadcastReceiver { if (GeckoApp.checkLaunchState(GeckoApp.LaunchState.GeckoRunning)) { GeckoAppShell.onLowMemory(); } + ScreenshotHandler.disableScreenshot(); GeckoAppShell.geckoEventSync(); } } - private synchronized boolean decreaseMemoryPressure() { - if (mMemoryPressure > 0) { - mMemoryPressure--; - Log.d(LOGTAG, "Decreased memory pressure to " + mMemoryPressure); - return true; + private boolean decreaseMemoryPressure() { + int newLevel; + synchronized (this) { + if (mMemoryPressure <= 0) { + return false; + } + + newLevel = --mMemoryPressure; } - return false; + Log.d(LOGTAG, "Decreased memory pressure to " + newLevel); + + if (newLevel == MEMORY_PRESSURE_NONE) { + ScreenshotHandler.enableScreenshot(); + } + + return true; } class PressureDecrementer implements Runnable { diff --git a/mobile/android/base/ScreenshotHandler.java b/mobile/android/base/ScreenshotHandler.java index 7431d8c2c91..7a36c5e4f2d 100644 --- a/mobile/android/base/ScreenshotHandler.java +++ b/mobile/android/base/ScreenshotHandler.java @@ -17,6 +17,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.opengl.GLES20; import android.util.FloatMath; +import android.util.Log; import java.nio.ByteBuffer; import java.util.Iterator; @@ -39,7 +40,7 @@ public final class ScreenshotHandler implements Runnable { private final int mMaxPixels; private final Queue mPendingScreenshots; - private final ByteBuffer mBuffer; + private ByteBuffer mBuffer; private int mBufferWidth; private int mBufferHeight; private RectF mPageRect; @@ -51,11 +52,16 @@ public final class ScreenshotHandler implements Runnable { private boolean mIsRepaintRunnablePosted; private static synchronized ScreenshotHandler getInstance() { + if (sDisableScreenshot) { + return null; + } if (sInstance == null) { try { sInstance = new ScreenshotHandler(); } catch (UnsupportedOperationException e) { - // initialization failed, fall through and return null + // initialization failed, fall through and return null. + // also set the disable flag so we don't try again. + sDisableScreenshot = true; } } return sInstance; @@ -76,13 +82,34 @@ public final class ScreenshotHandler implements Runnable { clearDirtyRect(); } + private void cleanup() { + discardPendingScreenshots(); + mBuffer = DirectBufferAllocator.free(mBuffer); + } + // Invoked via reflection from robocop test - public static void disableScreenshot() { + public static synchronized void disableScreenshot() { + if (sDisableScreenshot) { + return; + } sDisableScreenshot = true; + if (sInstance != null) { + sInstance.cleanup(); + sInstance = null; + } + Log.i(LOGTAG, "Screenshotting disabled"); + } + + public static synchronized void enableScreenshot() { + if (!sDisableScreenshot) { + return; + } + sDisableScreenshot = false; + Log.i(LOGTAG, "Screenshotting enabled"); } public static void screenshotWholePage(Tab tab) { - if (sDisableScreenshot || GeckoApp.mAppContext.isApplicationInBackground()) { + if (GeckoApp.mAppContext.isApplicationInBackground()) { return; } ScreenshotHandler handler = getInstance(); @@ -93,6 +120,14 @@ public final class ScreenshotHandler implements Runnable { handler.screenshotWholePage(tab.getId()); } + private void discardPendingScreenshots() { + synchronized (mPendingScreenshots) { + for (Iterator i = mPendingScreenshots.iterator(); i.hasNext(); ) { + i.next().discard(); + } + } + } + private void screenshotWholePage(int tabId) { LayerView layerView = GeckoApp.mAppContext.getLayerView(); if (layerView == null) { @@ -111,11 +146,7 @@ public final class ScreenshotHandler implements Runnable { mTabId = tabId; clearDirtyRect(); } - synchronized (mPendingScreenshots) { - for (Iterator i = mPendingScreenshots.iterator(); i.hasNext(); ) { - i.next().discard(); - } - } + discardPendingScreenshots(); int dstx = 0; int dsty = 0; @@ -140,9 +171,6 @@ public final class ScreenshotHandler implements Runnable { // Called from native code by JNI public static void notifyPaintedRect(float top, float left, float bottom, float right) { - if (sDisableScreenshot) { - return; - } ScreenshotHandler handler = getInstance(); if (handler == null) { return; diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index e56611a7c80..b9f716692d3 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -2480,6 +2480,9 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, int32_t srcX, int32 uint32_t stride = bufW * 2 /* 16 bpp */; void* data = env->GetDirectBufferAddress(buffer); + if (!data) + return NS_ERROR_FAILURE; + nsRefPtr surf = new gfxImageSurface(static_cast(data), nsIntSize(bufW, bufH), stride, gfxASurface::ImageFormatRGB16_565); if (surf->CairoStatus() != 0) { ALOG_BRIDGE("Error creating gfxImageSurface");