bug 704022 - PlaceholderLayerClient OOM at ByteBuffer.allocateDirect r=dougt
authorBrad Lassey <blassey@mozilla.com>
Wed, 30 Nov 2011 21:28:04 -0500
changeset 83647 0ff33522f0a3b0e30504abfaa04c0f92b50c2a3d
parent 83646 8e9a466b85bbee699a98cd21edea735466397e5d
child 83648 77a62cb00cc0c743a0ecc1bad1b69534f9cdc871
push idunknown
push userunknown
push dateunknown
reviewersdougt
bugs704022
milestone11.0a1
bug 704022 - PlaceholderLayerClient OOM at ByteBuffer.allocateDirect r=dougt
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/gfx/PlaceholderLayerClient.java
other-licenses/android/nsGeckoUtils.cpp
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1231,16 +1231,17 @@ abstract public class GeckoApp
             }
         });
     }
 
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
+        System.loadLibrary("mozutils");
         Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - onCreate");
         if (savedInstanceState != null) {
             mLastUri = savedInstanceState.getString(SAVED_STATE_URI);
             mLastTitle = savedInstanceState.getString(SAVED_STATE_TITLE);
             mLastViewport = savedInstanceState.getString(SAVED_STATE_VIEWPORT);
         }
         if (Build.VERSION.SDK_INT >= 9) {
             StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -131,16 +131,18 @@ public class GeckoAppShell
     public static native void notifyUriVisited(String uri);
     public static native boolean canCreateFixupURI(String text);
 
     public static native void processNextNativeEvent();
 
     public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
 
     public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
+    public static native ByteBuffer allocateDirectBuffer(long size);
+    public static native void freeDirectBuffer(ByteBuffer buf);
 
     // A looper thread, accessed by GeckoAppShell.getHandler
     private static class LooperThread extends Thread {
         public SynchronousQueue<Handler> mHandlerQueue =
             new SynchronousQueue<Handler>();
         
         public void run() {
             Looper.prepare();
@@ -287,17 +289,16 @@ public class GeckoAppShell
         return retVal;
     }
 
     // java-side stuff
     public static void loadGeckoLibs(String apkName) {
         // 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.
-        System.loadLibrary("mozutils");
         GeckoApp geckoApp = GeckoApp.mAppContext;
         String homeDir;
         if (Build.VERSION.SDK_INT < 8 ||
             geckoApp.getApplication().getPackageResourcePath().startsWith("/data") ||
             geckoApp.getApplication().getPackageResourcePath().startsWith("/system")) {
             File home = geckoApp.getFilesDir();
             homeDir = home.getPath();
             // handle the application being moved to phone from sdcard
--- a/mobile/android/base/gfx/PlaceholderLayerClient.java
+++ b/mobile/android/base/gfx/PlaceholderLayerClient.java
@@ -39,16 +39,17 @@ package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.gfx.BufferedCairoImage;
 import org.mozilla.gecko.gfx.CairoUtils;
 import org.mozilla.gecko.gfx.FloatSize;
 import org.mozilla.gecko.gfx.LayerClient;
 import org.mozilla.gecko.gfx.PointUtils;
 import org.mozilla.gecko.gfx.SingleTileLayer;
 import org.mozilla.gecko.GeckoApp;
+import org.mozilla.gecko.GeckoAppShell;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.os.AsyncTask;
 import android.os.Environment;
 import android.util.Log;
@@ -89,16 +90,20 @@ public class PlaceholderLayerClient exte
         }
     }
 
     public static PlaceholderLayerClient createInstance(Context context) {
         return new PlaceholderLayerClient(context);
     }
 
     public void destroy() {
+        if (mBuffer != null) {
+            GeckoAppShell.freeDirectBuffer(mBuffer);
+            mBuffer = null;
+        }
         if (mTask != null) {
             mTask.cancel(false);
             mTask = null;
         }
     }
 
     private class FetchImageTask extends AsyncTask<Void, Void, Void> {
 
@@ -113,17 +118,17 @@ public class PlaceholderLayerClient exte
 
             Bitmap.Config config = bitmap.getConfig();
 
             mWidth = bitmap.getWidth();
             mHeight = bitmap.getHeight();
             mFormat = CairoUtils.bitmapConfigToCairoFormat(config);
 
             int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat) / 8;
-            mBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * bpp);
+            mBuffer = GeckoAppShell.allocateDirectBuffer(mWidth * mHeight * bpp);
 
             bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
 
             if (mViewportUnknown) {
                 mViewport.setPageSize(new FloatSize(mWidth, mHeight));
                 if (getLayerController() != null)
                     getLayerController().setPageSize(mViewport.getPageSize());
             }
--- a/other-licenses/android/nsGeckoUtils.cpp
+++ b/other-licenses/android/nsGeckoUtils.cpp
@@ -48,8 +48,24 @@ Java_org_mozilla_gecko_GeckoAppShell_put
     // better to do here
     str = jenv->GetStringUTFChars(map, NULL);
     if (str == NULL)
         return;
     putenv(strdup(str));
     jenv->ReleaseStringUTFChars(map, str);
 }
 
+extern "C"
+__attribute__ ((visibility("default")))
+jobject JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *jenv, jclass, jlong size)
+{
+    return jenv->NewDirectByteBuffer(malloc(size), size);
+}
+
+extern "C"
+__attribute__ ((visibility("default")))
+void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_freeDirectBuffer(JNIEnv *jenv, jclass, jobject buf)
+{
+    free(jenv->GetDirectBufferAddress(buf));
+}
+