Bug 709103 - Optimize creating and saving thumbnail bitmaps r=blassey a=java-only
authorMark Finkle <mfinkle@mozilla.com>
Mon, 12 Dec 2011 13:50:35 -0500
changeset 84086 70096993b6d64887c3c8430dbf54b6c08a7e514a
parent 84085 34c34de2e9648b12da44475f748c429a354f20cf
child 84087 6992abaa6854c25baf2bfc6f38a3de6d04ba44e7
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey, java-only
bugs709103
milestone11.0a1
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
Bug 709103 - Optimize creating and saving thumbnail bitmaps r=blassey a=java-only
mobile/android/base/GeckoApp.java
mobile/android/base/Tab.java
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -558,31 +558,36 @@ abstract public class GeckoApp
     public String getLastViewport() {
         return mLastViewport;
     }
 
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         if (mOwnActivityDepth > 0)
             return; // we're showing one of our own activities and likely won't get paged out
+
         if (outState == null)
             outState = new Bundle();
-        mRememberLastScreenRunnable.run();
+
+        new SessionSnapshotRunnable(null).run();
+
         outState.putString(SAVED_STATE_URI, mLastUri);
         outState.putString(SAVED_STATE_TITLE, mLastTitle);
         outState.putString(SAVED_STATE_VIEWPORT, mLastViewport);
         outState.putByteArray(SAVED_STATE_SCREEN, mLastScreen);
     }
 
-    Runnable mRememberLastScreenRunnable = new Runnable() {; 
+    public class SessionSnapshotRunnable implements Runnable {
+        Tab mThumbnailTab;
+        SessionSnapshotRunnable(Tab thumbnailTab) {
+            mThumbnailTab = thumbnailTab;
+        }
+
         public void run() {
-            synchronized (this) {
-                if (mUserDefinedProfile)
-                    return;
-
+            synchronized (mSoftwareLayerClient) {
                 Tab tab = Tabs.getInstance().getSelectedTab();
                 if (tab == null)
                     return;
 
                 HistoryEntry lastHistoryEntry = tab.getLastHistoryEntry();
                 if (lastHistoryEntry == null)
                     return;
 
@@ -593,25 +598,29 @@ abstract public class GeckoApp
                     mLastTitle == lastHistoryEntry.mTitle)
                     return;
    
                 mLastViewport = mSoftwareLayerClient.getGeckoViewportMetrics().toJSON();
                 mLastUri = lastHistoryEntry.mUri;
                 mLastTitle = lastHistoryEntry.mTitle;
                 Bitmap bitmap = mSoftwareLayerClient.getBitmap();
                 if (bitmap != null) {
+                    // Make a thumbnail for the given tab, if it's still selected
+                    if (tab == mThumbnailTab)
+                        mThumbnailTab.updateThumbnail(bitmap);
+
                     ByteArrayOutputStream bos = new ByteArrayOutputStream();
                     bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
                     mLastScreen = bos.toByteArray();
                 } else {
                     mLastScreen = null;
                 }
             }
         }
-    };
+    }
 
     private void maybeCancelFaviconLoad(Tab tab) {
         long faviconLoadId = tab.getFaviconLoadId();
 
         if (faviconLoadId == Favicons.NOT_LOADING)
             return;
 
         // Cancel pending favicon load task
@@ -923,17 +932,17 @@ abstract public class GeckoApp
         mMainHandler.postAtFrontOfQueue(r);
     }
 
     public void hideAboutHome() {
         Runnable r = new AboutHomeRunnable(false);
         mMainHandler.postAtFrontOfQueue(r);
     }
 
-    public class  AboutHomeRunnable implements Runnable {
+    public class AboutHomeRunnable implements Runnable {
         boolean mShow;
         AboutHomeRunnable(boolean show) {
             mShow = show;
         }
 
         public void run() {
             if (mAboutHomeContent == null) {
                 mAboutHomeContent = (AboutHomeContent) findViewById(R.id.abouthome_content);
@@ -1018,20 +1027,16 @@ abstract public class GeckoApp
                 onTabsChanged(tab);
                 mBrowserToolbar.updateTabs(Tabs.getInstance().getCount());
                 mDoorHangerPopup.updatePopup();
             }
         });
     }
 
     void handleSelectTab(int tabId) {
-        Tab selTab = Tabs.getInstance().getSelectedTab();
-        if (selTab != null)
-            selTab.updateThumbnail(mSoftwareLayerClient.getBitmap());
-
         final Tab tab = Tabs.getInstance().selectTab(tabId);
         if (tab == null)
             return;
 
         if (tab.getURL().equals("about:home"))
             showAboutHome();
         else
             hideAboutHome();
@@ -1079,16 +1084,19 @@ abstract public class GeckoApp
 
         mMainHandler.post(new Runnable() {
             public void run() {
                 if (Tabs.getInstance().isSelectedTab(tab))
                     mBrowserToolbar.setProgressVisibility(false);
                 onTabsChanged(tab);
             }
         });
+
+        Runnable r = new SessionSnapshotRunnable(tab);
+        GeckoAppShell.getHandler().postDelayed(r, 500);
     }
 
     void handleShowToast(final String message, final String duration) {
         mMainHandler.post(new Runnable() {
             public void run() {
                 Toast toast;
                 if (duration.equals("long"))
                     toast = Toast.makeText(mAppContext, message, Toast.LENGTH_LONG);
@@ -1101,28 +1109,27 @@ abstract public class GeckoApp
 
     void handleContentLoaded(int tabId, String uri, String title) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         tab.updateTitle(title);
 
+        // Make the UI changes
         mMainHandler.post(new Runnable() {
             public void run() {
                 loadFavicon(tab);
 
-                if (Tabs.getInstance().isSelectedTab(tab)) {
+                if (Tabs.getInstance().isSelectedTab(tab))
                     mBrowserToolbar.setTitle(tab.getDisplayTitle());
-                    tab.updateThumbnail(mSoftwareLayerClient.getBitmap());
-                }
+
                 onTabsChanged(tab);
             }
         });
-        GeckoAppShell.getHandler().postDelayed(mRememberLastScreenRunnable, 500);
     }
 
     void handleTitleChanged(int tabId, String title) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         tab.updateTitle(title);
@@ -1497,17 +1504,18 @@ abstract public class GeckoApp
         }
     }
 
     @Override
     public void onPause()
     {
         Log.i(LOGTAG, "pause");
 
-        GeckoAppShell.getHandler().post(mRememberLastScreenRunnable);
+        Runnable r = new SessionSnapshotRunnable(null);
+        GeckoAppShell.getHandler().post(r);
 
         GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_PAUSING));
         // The user is navigating away from this activity, but nothing
         // has come to the foreground yet; for Gecko, we may want to
         // stop repainting, for example.
 
         // Whatever we do here should be fast, because we're blocking
         // the next activity from showing up until we finish.
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -53,16 +53,17 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
 import org.mozilla.gecko.db.BrowserDB;
 
 public class Tab {
     public static enum AgentMode { MOBILE, DESKTOP };
     private static final String LOGTAG = "GeckoTab";
+    private static final int kThumbnailSize = 96;
 
     static int sMinDim = 0;
     private int mId;
     private String mUrl;
     private String mTitle;
     private Drawable mFavicon;
     private String mFaviconUrl;
     private String mSecurityMode;
@@ -136,17 +137,18 @@ public class Tab {
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 if (sMinDim == 0) {
                     DisplayMetrics metrics = new DisplayMetrics();
                     GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
                     sMinDim = Math.min(metrics.widthPixels, metrics.heightPixels);
                 }
                 if (b != null) {
-                    Bitmap bitmap = Bitmap.createBitmap(b, 0, 0, sMinDim, sMinDim);
+                    Bitmap cropped = Bitmap.createBitmap(b, 0, 0, sMinDim, sMinDim);
+                    Bitmap bitmap = Bitmap.createScaledBitmap(cropped, kThumbnailSize, kThumbnailSize, false);
                     mThumbnail = new BitmapDrawable(bitmap);
                     saveThumbnailToDB((BitmapDrawable) mThumbnail);
                 } else {
                     mThumbnail = null;
                 }
             }
         });
     }
@@ -402,10 +404,9 @@ public class Tab {
 
     public void setAgentMode(AgentMode agentMode) {
         mAgentMode = agentMode;
     }
 
     public AgentMode getAgentMode() {
         return mAgentMode;
     }
-
 }