Back out e64522db8661 (bug 863288) for robocop-1 hangs
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 23 Apr 2013 20:52:59 -0700
changeset 140658 96c0eae610a29d7cffa7581f1e54018368fd26ed
parent 140657 bfe45fd605f8920010bd99c2156678704d1d51b5
child 140659 95262d6936423d885c738e4481679e457f6ff9f8
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs863288
milestone23.0a1
backs oute64522db8661d713d1af37abff87997d0128317c
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Back out e64522db8661 (bug 863288) for robocop-1 hangs
mobile/android/base/AwesomeBar.java
mobile/android/base/GeckoApp.java
mobile/android/base/ThumbnailHelper.java
mobile/android/base/awesomebar/AllPagesTab.java
mobile/android/base/awesomebar/AwesomeBarTab.java
mobile/android/base/awesomebar/HistoryTab.java
mobile/android/base/db/LocalBrowserDB.java
mobile/android/base/gfx/BitmapUtils.java
mobile/android/base/widget/TopSitesView.java
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -2,29 +2,29 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.db.BrowserContract.Combined;
 import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.util.GamepadUtils;
 import org.mozilla.gecko.util.StringUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.UiAsyncTask;
 
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.TextWatcher;
@@ -672,19 +672,18 @@ public class AwesomeBar extends GeckoAct
             }
             case R.id.add_to_launcher: {
                 if (url == null) {
                     Log.e(LOGTAG, "Can't add to home screen because URL is null");
                     break;
                 }
 
                 Bitmap bitmap = null;
-                if (b != null) {
-                    bitmap = BitmapUtils.decodeByteArray(b);
-                }
+                if (b != null)
+                    bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
 
                 String shortcutTitle = TextUtils.isEmpty(title) ? url.replaceAll("^([a-z]+://)?(www\\.)?", "") : title;
                 GeckoAppShell.createShortcut(shortcutTitle, url, bitmap, "");
                 break;
             }
             case R.id.share: {
                 if (url == null) {
                     Log.e(LOGTAG, "Can't share because URL is null");
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -2,17 +2,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.background.announcements.AnnouncementsBroadcastService;
 import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.gfx.Layer;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.gfx.PanZoomController;
 import org.mozilla.gecko.gfx.PluginLayer;
 import org.mozilla.gecko.gfx.PointUtils;
 import org.mozilla.gecko.updater.UpdateService;
 import org.mozilla.gecko.updater.UpdateServiceHelper;
 import org.mozilla.gecko.util.GeckoEventListener;
@@ -1152,47 +1151,47 @@ abstract public class GeckoApp
                 options.inJustDecodeBounds = true;
                 Bitmap image = null;
                 InputStream is = null;
                 ByteArrayOutputStream os = null;
                 try{
                     if (isDataURI) {
                         int dataStart = aSrc.indexOf(',');
                         byte[] buf = Base64.decode(aSrc.substring(dataStart+1), Base64.DEFAULT);
-                        BitmapUtils.decodeByteArray(buf, options);
+                        BitmapFactory.decodeByteArray(buf, 0, buf.length, options);
                         options.inSampleSize = getBitmapSampleSize(options, idealWidth, idealHeight);
                         options.inJustDecodeBounds = false;
-                        image = BitmapUtils.decodeByteArray(buf, options);
+                        image = BitmapFactory.decodeByteArray(buf, 0, buf.length, options);
                     } else {
                         int byteRead;
                         byte[] buf = new byte[4192];
                         os = new ByteArrayOutputStream();
                         URL url = new URL(aSrc);
                         is = url.openStream();
 
                         // Cannot read from same stream twice. Also, InputStream from
                         // URL does not support reset. So converting to byte array
 
                         while((byteRead = is.read(buf)) != -1) {
                             os.write(buf, 0, byteRead);
                         }
                         byte[] imgBuffer = os.toByteArray();
-                        BitmapUtils.decodeByteArray(imgBuffer, options);
+                        BitmapFactory.decodeByteArray(imgBuffer, 0, imgBuffer.length, options);
                         options.inSampleSize = getBitmapSampleSize(options, idealWidth, idealHeight);
                         options.inJustDecodeBounds = false;
-                        image = BitmapUtils.decodeByteArray(imgBuffer, options);
+                        image = BitmapFactory.decodeByteArray(imgBuffer, 0, imgBuffer.length, options);
                     }
                     if(image != null) {
                         mgr.setBitmap(image);
                         return true;
                     } else {
                         return false;
                     }
                 } catch(OutOfMemoryError ome) {
-                    Log.e(LOGTAG, "Out of Memory when converting to byte array", ome);
+                    Log.e(LOGTAG, "Out of Memmory when coverting to byte array", ome);
                     return false;
                 } catch(IOException ioe) {
                     Log.e(LOGTAG, "I/O Exception while setting wallpaper", ioe);
                     return false;
                 } finally {
                     if(is != null) {
                         try {
                             is.close();
--- a/mobile/android/base/ThumbnailHelper.java
+++ b/mobile/android/base/ThumbnailHelper.java
@@ -1,21 +1,21 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.mozglue.DirectBufferAllocator;
 
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.util.Log;
 
 import java.nio.ByteBuffer;
 import java.util.LinkedList;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Helper class to generate thumbnails for tabs.
@@ -182,22 +182,26 @@ public final class ThumbnailHelper {
     private void processThumbnailData(Tab tab, ByteBuffer data) {
         Bitmap b = tab.getThumbnailBitmap(mWidth, mHeight);
         data.position(0);
         b.copyPixelsFromBuffer(data);
         setTabThumbnail(tab, b, null);
     }
 
     private void setTabThumbnail(Tab tab, Bitmap bitmap, byte[] compressed) {
-        if (bitmap == null) {
-            if (compressed == null) {
-                Log.w(LOGTAG, "setTabThumbnail: one of bitmap or compressed must be non-null!");
-                return;
+        try {
+            if (bitmap == null) {
+                if (compressed == null) {
+                    Log.w(LOGTAG, "setTabThumbnail: one of bitmap or compressed must be non-null!");
+                    return;
+                }
+                bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length);
             }
-            bitmap = BitmapUtils.decodeByteArray(compressed);
+            tab.updateThumbnail(bitmap);
+        } catch (OutOfMemoryError ome) {
+            Log.w(LOGTAG, "setTabThumbnail: decoding byte array of length " + compressed.length + " ran out of memory");
         }
-        tab.updateThumbnail(bitmap);
     }
 
     private boolean shouldUpdateThumbnail(Tab tab) {
         return (Tabs.getInstance().isSelectedTab(tab) || GeckoApp.mAppContext.areTabsShown());
     }
 }
--- a/mobile/android/base/awesomebar/AllPagesTab.java
+++ b/mobile/android/base/awesomebar/AllPagesTab.java
@@ -19,16 +19,17 @@ import org.mozilla.gecko.util.UiAsyncTas
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import android.app.Activity;
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.ContextMenu;
@@ -892,18 +893,18 @@ public class AllPagesTab extends Awesome
                 return;
 
             do {
                 final String url = c.getString(c.getColumnIndexOrThrow(Combined.URL));
                 final byte[] b = c.getBlob(c.getColumnIndexOrThrow(Combined.FAVICON));
                 if (b == null)
                     continue;
 
-                Bitmap favicon = BitmapUtils.decodeByteArray(b);
-                if (favicon == null)
+                Bitmap favicon = BitmapFactory.decodeByteArray(b, 0, b.length);
+                if (favicon == null || favicon.getWidth() <= 0 || favicon.getHeight() <= 0)
                     continue;
 
                 favicon = Favicons.getInstance().scaleImage(favicon);
                 Favicons.getInstance().putFaviconInMemCache(url, favicon);
             } while (c.moveToNext());
         } finally {
             if (c != null)
                 c.close();
--- a/mobile/android/base/awesomebar/AwesomeBarTab.java
+++ b/mobile/android/base/awesomebar/AwesomeBarTab.java
@@ -2,23 +2,23 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.AwesomeBar.ContextMenuSubject;
 import org.mozilla.gecko.db.BrowserDB.URLColumns;
-import org.mozilla.gecko.gfx.BitmapUtils;
 
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.text.TextUtils;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -86,18 +86,18 @@ abstract public class AwesomeBarTab {
         }
         return mResources;
     }
 
     protected void updateFavicon(ImageView faviconView, Cursor cursor) {
         byte[] b = cursor.getBlob(cursor.getColumnIndexOrThrow(URLColumns.FAVICON));
         Bitmap favicon = null;
         if (b != null) {
-            Bitmap bitmap = BitmapUtils.decodeByteArray(b);
-            if (bitmap != null) {
+            Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
+            if (bitmap != null && bitmap.getWidth() > 0 && bitmap.getHeight() > 0) {
                 favicon = Favicons.getInstance().scaleImage(bitmap);
             }
         }
         updateFavicon(faviconView, favicon);
     }
 
     protected void updateFavicon(ImageView faviconView, Bitmap bitmap) {
         if (bitmap == null) {
--- a/mobile/android/base/awesomebar/HistoryTab.java
+++ b/mobile/android/base/awesomebar/HistoryTab.java
@@ -4,34 +4,35 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.AwesomeBar.ContextMenuSubject;
 import org.mozilla.gecko.db.BrowserContract.Combined;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.BrowserDB.URLColumns;
-import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.util.GamepadUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.MenuInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ExpandableListView;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.SimpleExpandableListAdapter;
 import android.widget.TextView;
@@ -187,18 +188,18 @@ public class HistoryTab extends AwesomeB
 
             viewHolder.titleView.setText(title);
             viewHolder.urlView.setText(url);
 
             byte[] b = (byte[]) historyItem.get(URLColumns.FAVICON);
             Bitmap favicon = null;
 
             if (b != null) {
-                Bitmap bitmap = BitmapUtils.decodeByteArray(b);
-                if (bitmap != null) {
+                Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
+                if (bitmap != null && bitmap.getWidth() > 0 && bitmap.getHeight() > 0) {
                     favicon = Favicons.getInstance().scaleImage(bitmap);
                 }
             }
             updateFavicon(viewHolder.faviconView, favicon);
 
             Integer bookmarkId = (Integer) historyItem.get(Combined.BOOKMARK_ID);
             Integer display = (Integer) historyItem.get(Combined.DISPLAY);
 
--- a/mobile/android/base/db/LocalBrowserDB.java
+++ b/mobile/android/base/db/LocalBrowserDB.java
@@ -9,25 +9,25 @@ import org.mozilla.gecko.db.BrowserContr
 import org.mozilla.gecko.db.BrowserContract.Combined;
 import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
 import org.mozilla.gecko.db.BrowserContract.FaviconColumns;
 import org.mozilla.gecko.db.BrowserContract.Favicons;
 import org.mozilla.gecko.db.BrowserContract.History;
 import org.mozilla.gecko.db.BrowserContract.SyncColumns;
 import org.mozilla.gecko.db.BrowserContract.Thumbnails;
 import org.mozilla.gecko.db.BrowserContract.URLColumns;
-import org.mozilla.gecko.gfx.BitmapUtils;
 
 import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.CursorWrapper;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
 import android.provider.Browser;
 import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.ByteArrayOutputStream;
 import java.util.Collection;
@@ -702,23 +702,24 @@ public class LocalBrowserDB implements B
                             null);
 
         if (!c.moveToFirst()) {
             c.close();
             return null;
         }
 
         int faviconIndex = c.getColumnIndexOrThrow(Combined.FAVICON);
+
         byte[] b = c.getBlob(faviconIndex);
         c.close();
 
         if (b == null)
             return null;
 
-        return BitmapUtils.decodeByteArray(b);
+        return BitmapFactory.decodeByteArray(b, 0, b.length);
     }
 
     @Override
     public String getFaviconUrlForHistoryUrl(ContentResolver cr, String uri) {
         Cursor c = cr.query(mHistoryUriWithProfile,
                             new String[] { History.FAVICON_URL },
                             Combined.URL + " = ?",
                             new String[] { uri },
--- a/mobile/android/base/gfx/BitmapUtils.java
+++ b/mobile/android/base/gfx/BitmapUtils.java
@@ -9,52 +9,16 @@ import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.util.Base64;
 import android.util.Log;
 
 public final class BitmapUtils {
     private static final String LOGTAG = "GeckoBitmapUtils";
 
-    private BitmapUtils() {}
-
-    public static Bitmap decodeByteArray(byte[] bytes) {
-        return decodeByteArray(bytes, null);
-    }
-
-    public static Bitmap decodeByteArray(byte[] bytes, BitmapFactory.Options options) {
-        if (bytes.length <= 0) {
-            throw new IllegalArgumentException("bytes.length " + bytes.length
-                                               + " must be a positive number");
-        }
-
-        Bitmap bitmap = null;
-        try {
-            bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
-        } catch (OutOfMemoryError e) {
-            Log.e(LOGTAG, "decodeByteArray(bytes.length=" + bytes.length
-                          + ", options= " + options + ") OOM!", e);
-            return null;
-        }
-
-        if (bitmap == null) {
-            Log.w(LOGTAG, "decodeByteArray() returning null because BitmapFactory returned null");
-            return null;
-        }
-
-        if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
-            Log.w(LOGTAG, "decodeByteArray() returning null because BitmapFactory returned "
-                          + "a bitmap with dimensions " + bitmap.getWidth()
-                          + "x" + bitmap.getHeight());
-            return null;
-        }
-
-        return bitmap;
-    }
-
     public static int getDominantColor(Bitmap source) {
         return getDominantColor(source, true);
     }
 
     public static int getDominantColor(Bitmap source, boolean applyThreshold) {
       int[] colors = new int[37];
       int[] sat = new int[11];
       int[] val = new int[11];
@@ -105,16 +69,16 @@ public final class BitmapUtils {
      *
      * @param dataURI a Base64-encoded data URI string
      * @return        the decoded bitmap, or null if the data URI is invalid
      */
     public static Bitmap getBitmapFromDataURI(String dataURI) {
         String base64 = dataURI.substring(dataURI.indexOf(',') + 1);
         try {
             byte[] raw = Base64.decode(base64, Base64.DEFAULT);
-            return BitmapUtils.decodeByteArray(raw);
+            return BitmapFactory.decodeByteArray(raw, 0, raw.length);
         } catch (Exception e) {
             Log.e(LOGTAG, "exception decoding bitmap from data URI: " + dataURI, e);
         }
         return null;
     }
 }
 
--- a/mobile/android/base/widget/TopSitesView.java
+++ b/mobile/android/base/widget/TopSitesView.java
@@ -10,27 +10,27 @@ import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.ThumbnailHelper;
 import org.mozilla.gecko.db.BrowserContract.Thumbnails;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.BrowserDB.TopSitesCursorWrapper;
 import org.mozilla.gecko.db.BrowserDB.URLColumns;
-import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.util.ActivityResultHandler;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.UiAsyncTask;
 
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.shapes.PathShape;
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -311,17 +311,17 @@ public class TopSitesView extends GridVi
                 return thumbnails;
 
             do {
                 final String url = c.getString(c.getColumnIndexOrThrow(Thumbnails.URL));
                 final byte[] b = c.getBlob(c.getColumnIndexOrThrow(Thumbnails.DATA));
                 if (b == null)
                     continue;
 
-                Bitmap thumbnail = BitmapUtils.decodeByteArray(b);
+                Bitmap thumbnail = BitmapFactory.decodeByteArray(b, 0, b.length);
                 if (thumbnail == null)
                     continue;
 
                 thumbnails.put(url, thumbnail);
             } while (c.moveToNext());
         } finally {
             if (c != null)
                 c.close();
@@ -651,17 +651,17 @@ public class TopSitesView extends GridVi
                         Cursor c = BrowserDB.getThumbnailsForUrls(resolver, urls);
                         if (c == null || !c.moveToFirst()) {
                             return null;
                         }
 
                         final byte[] b = c.getBlob(c.getColumnIndexOrThrow(Thumbnails.DATA));
                         Bitmap bitmap = null;
                         if (b != null) {
-                            bitmap = BitmapUtils.decodeByteArray(b);
+                            bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
                         }
                         c.close();
 
                         return bitmap;
                     }
 
                     @Override
                     public void onPostExecute(Bitmap b) {